2d – Unity Raycast does not detect layers

I have problems with layer detection using raycasts.

Context: I have created a raster for use in a pathfinding algorithm on a 2D plane. I would now like to implement different weights according to the layer in which each node of the grid is located, e.g. A knot in a normal terrain has a terrainPenalty of 1 and more difficult terrain of 2 or more. To detect the terrain type in the 2D plane, I make a raycast at the node location for each node that was previously considered walkable. The problem now occurs because I've noticed that the paths created neglect such values. This is the code snippet that causes me problems:

            if (walkable)
            {
                Ray ray = new Ray(worldPoint + Vector3.back * 10, Vector3.forward);//PROBLEM HERE (NOT DETECTING PENALTIES)
                RaycastHit hit;
                walkableMask = ~walkableMask;
                if (Physics.Raycast(ray, out hit, 100, walkableMask))
                {
                    walkableRegionsDictionary.TryGetValue(hit.collider.gameObject.layer, out terrainPenalty );
                }
            }

At first, I thought the problem was how the layers are called, because I created a layer mask that combines two layers with the bitwise OR operator, but then I tried to mess around with all the layers (why is that? ) walkableMask = ~walkableMask; now). The result was always a wrong issue for Physics.Raycast(ray, out hit, 100, walkableMask),

I thought I might have gotten the wrong coordinates for the ray, but I made some gizmos to see if the ray pierced my plane vertically and did so. I've also tried switching levels to see if something works, but the output is always wrong. What am I doing wrong? Here's the rest of the feature, if needed, I can also upload the entire script:

    void CreateGrid()
{
    grid = new Node1(gridSizeX, gridSizeY);
    Vector3 worldBottomLeft = transform.position - Vector3.right * gridWorldSize.x / 2 - Vector3.up * gridWorldSize.y / 2;

    for (int x = 0; x < gridSizeX; x++)
    {
        for (int y = 0; y < gridSizeY; y++)
        {
            Vector3 worldPoint = worldBottomLeft + Vector3.right * (x * nodeDiameter + nodeRadius) + Vector3.up * (y * nodeDiameter + nodeRadius);
            bool walkable = !(Physics2D.OverlapCircle(new Vector2(worldPoint.x, worldPoint.y), nodeRadius, unwalkableMask));
            //bool walkable = !(Physics.CheckSphere(worldPoint, nodeRadius));

            int terrainPenalty = 0;

            if (walkable)
            {
                Ray ray = new Ray(worldPoint + Vector3.back * 10, Vector3.forward);//PROBLEM HERE (NOT DETECTING PENALTIES)
                RaycastHit hit;
                walkableMask = ~walkableMask;
                if (Physics.Raycast(ray, out hit, 100, walkableMask))
                {
                    walkableRegionsDictionary.TryGetValue(hit.collider.gameObject.layer, out terrainPenalty );
                }
            }

            grid(x, y) = new Node1(walkable, worldPoint, x, y, terrainPenalty);
        }            
    }
}

Thanks for any hints, I do not know what else to try: .

unity – educational game development

Good people from Stack Exchange, I need your best advice.

I am a computer science student in Indonesia and am currently pursuing a career in game development with the Unity Game Engine. So far I have doubts and problems learning how to program games, because in real life I do not have a teacher who could teach me how to make a game. Because of this, I have to rely on online material and learn by myself to learn about game programming.

My dream is to develop 3D computer games in my country, set a new high standard in Indonesian game development, and teach my brothers and sisters in game development.

I already have basic knowledge of C #, but when I tried to learn, there were some keywords and terms that I do not yet understand (like coroutines, quaternions, etc.), which leads me to open the documentation pages of Microsoft or Unity. This slows down my learning process. After learning C #, I tried to learn basic scripting from Unity's Unity.learn website. Here I also tried to ask questions on certain functions and solutions in the Unity Forums. I also completed a Brackeys 3D game tutorial to create a 3D game. However, I feel that I do not learn game development right.

Honestly, I feel a bit lost and unmotivated, because the progress I've made so far is quite small. I'm not sure if this is normal while learning the game development. I am currently attending an online game development course by agate.dilo.id that helps a bit, but I wonder if there are any other ways to learn how to develop games. It would be nice if someone could give me some advice on how to effectively learn game development so I can make games with a similar standard to the US / Europe.

Unity – Why does my A * algorithm not consider future obstacles?

I'm pretty new to programming, unity and game design in general.
I'm following an old A * unity tutorial by Sebastian Lang, and the algorithm he uses seems to be incorrect in terms of obstacles that are not right next to the path.

This is the current result of my code

Enter image description here

So … not quite optimal. As you can see, from bottom to top, it tries to match the x-value of the target, but the first block is in the way. As soon as the block ends, it successfully matches the x-value of the target, but then has to bypass the second block. Optimally, it would know that the only real obstacle is the 2nd block.

It's possible he'll come back later in another future video and fix this problem since I'm only in 5/10 videos; However, I would rather practice as a programmer to think than to find out exactly what to do.

As a solution, I would draw a kind of obstacle check line from start to finish and use the position data of the intersecting obstacles as a reference for the maximum distance that the path has to cover in a particular axis. But even then, some obstacle layouts would not work because an obstacle can block the way without being exactly between the two points.

I'm not sure where to go from here, so any advice would be helpful.

The main concepts are in pseudocode, so even those who do not know C # can help.

The pathfinding is calculated with the following pseudocode …

h_cost = distance from start node
g_cost = distance from target node
f_cost = h_cost + g_cost

Get the start node position
Get the target node position

create an OPEN set for nodes that need to be evaluated
create a CLOSED set for nodes that have already been evaluated
add start node to OPEN

loop
     current = node with lowest f_cost
     move current from OPEN to CLOSED

     if current is the target node
          return

     for each neighbor of current (4 cardinal sides, and 4 diagonals)
          if unwalkable (an obstacle) OR in Closed
               continue

          if new path to neighbor is shorter OR neighbor is not in OPEN
               set f_cost of neighbor
               set parent of neighbor to current
               if neighbor is not in OPEN
                    add neighbor to OPEN

The distance is calculated with the following pseudocode

 Distance between start and target x-value = x
 Distance between start and target y-value = y

 If x > y, then 14 * y + 10 * (x - y)  
 If x < y, then 14 * x + 10 * (y - x)

Heap.cs

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using System;

    public class Heap where T : IHeapItem {

        T() items;
        int currentItemCount;

        public Heap(int maxHeapSize) {
            items = new T(maxHeapSize);
        }

        public void Add(T item) {
            item.HeapIndex = currentItemCount;
            items(currentItemCount) = item;
            SortUp(item);
            currentItemCount++;
        }

        public T RemoveFirst() {
            T firstItem = items(0);
            currentItemCount--;
            items(0) = items(currentItemCount);
            items(0).HeapIndex = 0;
            SortDown(items(0));
            return firstItem;
        }

        public void UpdateItem(T item) {
            SortUp(item);
        }

        public int Count {
            get {
                return currentItemCount;
            }
        }

        public bool Contains(T item) {
            return Equals(items(item.HeapIndex), item);
        }

        void SortDown(T item) {
            while (true) {
                int childIndexLeft = item.HeapIndex * 2 + 1;
                int childIndexRight = item.HeapIndex * 2 + 2;
                int swapIndex = 0;

                if (childIndexLeft < currentItemCount) {
                    swapIndex = childIndexLeft;

                    if (childIndexRight < currentItemCount) {
                        if (items(childIndexLeft).CompareTo(items(childIndexRight)) < 0) {
                            swapIndex = childIndexRight;
                        }
                    }

                    if (item.CompareTo(items(swapIndex)) < 0) {
                        Swap(item, items(swapIndex));
                    }
                    else {
                        return;
                    }
                }
                else {
                    return;
                }
            }
        }

        void SortUp(T item) {
            int parentIndex = (item.HeapIndex - 1) / 2;

            while (true) {
                T parentItem = items(parentIndex);
                if (item.CompareTo(parentItem) > 0) {
                    Swap(item, parentItem);
                }
                else {
                    break;
                }

                parentIndex = (item.HeapIndex - 1) / 2;
            }
        }

        void Swap(T itemA, T itemB) {
            items(itemA.HeapIndex) = itemB;
            items(itemB.HeapIndex) = itemA;
            int itemAIndex = itemA.HeapIndex;
            itemA.HeapIndex = itemB.HeapIndex;
            itemB.HeapIndex = itemAIndex;
        }

    }


    public interface IHeapItem : IComparable { 
        int HeapIndex {
            get;
            set;
        }
    }

Grid.cs

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;

    public class Grid : MonoBehaviour {

        public bool onlyDisplayPathGizmos;
        public Transform player;
        public LayerMask unwalkableMask;
        public Vector2 gridWorldSize;
        public float nodeRadius;
        Node(,) grid;

        float nodeDiameter;
        int gridSizeX, gridSizeY;

        void Start() {
            nodeDiameter = nodeRadius * 2;
            gridSizeX = Mathf.RoundToInt(gridWorldSize.x / nodeDiameter);
            gridSizeY = Mathf.RoundToInt(gridWorldSize.y / nodeDiameter);
            CreateGrid();
        }

        public int MaxSize {
            get {
                return gridSizeX * gridSizeY;
            }
        }

        void CreateGrid() {
            grid = new Node(gridSizeX, gridSizeY);
            Vector3 worldBottomLeft = transform.position - Vector3.right * gridWorldSize.x / 2 - Vector3.forward * gridWorldSize.y / 2;

            for (int x = 0; x < gridSizeX; x++) {
                for (int y = 0; y < gridSizeY; y++) {
                    Vector3 worldPoint = worldBottomLeft + Vector3.right * (x * nodeDiameter + nodeRadius) + Vector3.forward * (y * nodeDiameter + nodeRadius);
                    bool walkable = !(Physics.CheckSphere(worldPoint, nodeRadius, unwalkableMask));
                    grid(x, y) = new Node(walkable, worldPoint, x, y);
                }
            }
        }

        public List GetNeighbors(Node node) {
            List neighbors = new List();

            for (int x = -1; x <= 1; x++) {
                for (int y = -1; y <= 1; y++) {
                    if (x == 0 && y == 0)
                        continue;

                    int checkX = node.gridX + x;
                    int checkY = node.gridY + y;

                    if (checkX >= 0 && checkX < gridSizeX && checkY >= 0 && checkY < gridSizeY) {
                        neighbors.Add(grid(checkX, checkY));
                    }
                }
            }

            return neighbors;
        }
        public Node NodeFromWorldPoint(Vector3 worldPosition) {
            float percentX = (worldPosition.x + gridWorldSize.x / 2) / gridWorldSize.x;
            float percentY = (worldPosition.z + gridWorldSize.y / 2) / gridWorldSize.y;
            percentX = Mathf.Clamp01(percentX);
            percentY = Mathf.Clamp01(percentY);

            int x = Mathf.RoundToInt((gridSizeX - 1) * percentX);
            int y = Mathf.RoundToInt((gridSizeY - 1) * percentY);
            return grid(x, y);
        }

        public List path;
        void OnDrawGizmos() {
            Gizmos.DrawWireCube(transform.position, new Vector3(gridWorldSize.x, 1, gridWorldSize.y));

            if (onlyDisplayPathGizmos) {
                if (path != null) {
                    foreach (Node n in path) {
                        Gizmos.color = Color.black;
                        Gizmos.DrawCube(n.worldPosition, Vector3.one * (nodeDiameter - .1f));
                    }
                }
            }
            else {
                if (grid != null) {
                    Node playerNode = NodeFromWorldPoint(player.position);
                    foreach (Node n in grid) {
                        Gizmos.color = (n.walkable) ? Color.white : Color.red;
                        if (path != null)
                            if (path.Contains(n))
                                Gizmos.color = Color.black;
                        Gizmos.DrawCube(n.worldPosition, Vector3.one * (nodeDiameter - .1f));
                    }
                }
            }
        }
    }

Node.cs

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;

    public class Node : IHeapItem {

        public bool walkable;
        public Vector3 worldPosition;
        public int gridX;
        public int gridY;

        public int gCost;
        public int hCost;
        public Node parent;
        int heapIndex;


        public Node(bool _walkable, Vector3 _worldPos, int _gridX, int _gridY) {
            walkable = _walkable;
            worldPosition = _worldPos;
            gridX = _gridX;
            gridY = _gridY;
        }

        public int fCost {
            get {
                return gCost = hCost;
            }
        }

        public int HeapIndex {
            get {
                return heapIndex;
            }
            set {
                heapIndex = value;
            }
        }

        public int CompareTo(Node nodeToCompare) {
            int compare = fCost.CompareTo(nodeToCompare.fCost);
            if (compare == 0) {
                compare = hCost.CompareTo(nodeToCompare.hCost);
            }
            return -compare;
        }

    }

Pathfinding.cs

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using System.Diagnostics;
    public class Pathfinding : MonoBehaviour {

        public Transform seeker, target;

        Grid grid;

        void Awake() {
            grid = GetComponent();
        }

        void Update() {
            FindPath(seeker.position, target.position);
        }

        void FindPath(Vector3 startPos, Vector3 targetPos) {

            Stopwatch sw = new Stopwatch();
            sw.Start();

            Node startNode = grid.NodeFromWorldPoint(startPos);
            Node targetNode = grid.NodeFromWorldPoint(targetPos);

            Heap openSet = new Heap(grid.MaxSize);
            HashSet closedSet = new HashSet();
            openSet.Add(startNode);

            while (openSet.Count > 0) {
                Node currentNode = openSet.RemoveFirst();
                closedSet.Add(currentNode);

                if (currentNode == targetNode) {
                    sw.Stop();
                    print("Path found: " + sw.ElapsedMilliseconds + " ms");
                    RetracePath(startNode, targetNode);
                    return;
                }

                foreach (Node neighbor in grid.GetNeighbors(currentNode)) {
                    if (!neighbor.walkable || closedSet.Contains(neighbor)) {
                        continue;
                    }

                    int newMovementCostToNeighbor = currentNode.gCost + GetDistance(currentNode, neighbor);
                    if (newMovementCostToNeighbor < neighbor.gCost || !openSet.Contains(neighbor)) {
                        neighbor.gCost = newMovementCostToNeighbor;
                        neighbor.hCost = GetDistance(neighbor, targetNode);
                        neighbor.parent = currentNode;

                        if (!openSet.Contains(neighbor))
                            openSet.Add(neighbor);
                    }
                }
            }
        }

        void RetracePath(Node startNode, Node endNode) {
            List path = new List();
            Node currentNode = endNode;

            while (currentNode != startNode) {
                path.Add(currentNode);
                currentNode = currentNode.parent;
            }
            path.Reverse();

            grid.path = path;


        }

        int GetDistance(Node nodeA, Node nodeB) {
            int dstX = Mathf.Abs(nodeA.gridX - nodeB.gridX);
            int dstY = Mathf.Abs(nodeA.gridY - nodeB.gridY);

            if (dstX > dstY)
                return 14 * dstY + 10 * (dstX - dstY);
            return 14 * dstX + 10 * (dstY - dstX);

        }

    }

Unity – Recognize gradients and gradients to switch between character animations

Since the system you are using is at least partially successful, I would suggest that there are two options here:

The temporary problem is due to the capsule collider on the player controller selecting the first collision hit in the list (I suppose). You can try to wrap all hits into an array and loop them to find the hit with the lowest or highest Y value. Then use it with your existing normal exam. The nature of the shape of the collider can trigger a series of hits, and their order is not always guaranteed.

The second option I used to change the walking speed based on the slope is to fire a beam from a fixed point in front of the character and use the height difference between the Y of the player transformation and the beam pressures Y to increase the slope to determine. This is more accurate when you scan a single point.

My A * algorithm does not consider future obstacles. Unity with C #

I'm pretty new to programming, unity and game design in general.
I'm following an old A * unity tutorial by Sebastian Lang, and the algorithm he uses seems to be incorrect in terms of obstacles that are not right next to the path.

This is the current result of my code

Enter image description here

So … not quite optimal. As you can see, from bottom to top, it tries to match the x-value of the target, but the first block is in the way. As soon as the block ends, it successfully matches the x-value of the target, but then has to bypass the second block. Optimally, it would know that the only real obstacle is the 2nd block.

It's possible he'll come back later in another future video and fix this problem since I'm only in 5/10 videos; However, I would rather practice as a programmer to think than to find out exactly what to do.

As a solution, I would draw a kind of obstacle check line from start to finish and use the position data of the intersecting obstacles as a reference for the maximum distance that the path has to cover in a particular axis. But even then, some obstacle layouts would not work because an obstacle can block the way without being exactly between the two points.

I'm not sure where to go from here, so any advice would be helpful.

The main concepts are in pseudocode, so even those who do not know C # can help.

The pathfinding is calculated with the following pseudocode …

h_cost = distance from start node
g_cost = distance from target node
f_cost = h_cost + g_cost

Get the start node position
Get the target node position

create an OPEN set for nodes that need to be evaluated
create a CLOSED set for nodes that have already been evaluated
add start node to OPEN

loop
     current = node with lowest f_cost
     move current from OPEN to CLOSED

     if current is the target node
          return

     for each neighbor of current (4 cardinal sides, and 4 diagonals)
          if unwalkable (an obstacle) OR in Closed
               continue

          if new path to neighbor is shorter OR neighbor is not in OPEN
               set f_cost of neighbor
               set parent of neighbor to current
               if neighbor is not in OPEN
                    add neighbor to OPEN

The distance is calculated with the following pseudocode

 Distance between start and target x-value = x
 Distance between start and target y-value = y

 If x > y, then 14 * y + 10 * (x - y)  
 If x < y, then 14 * x + 10 * (y - x)

Heap.cs

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using System;

    public class Heap where T : IHeapItem {

        T() items;
        int currentItemCount;

        public Heap(int maxHeapSize) {
            items = new T(maxHeapSize);
        }

        public void Add(T item) {
            item.HeapIndex = currentItemCount;
            items(currentItemCount) = item;
            SortUp(item);
            currentItemCount++;
        }

        public T RemoveFirst() {
            T firstItem = items(0);
            currentItemCount--;
            items(0) = items(currentItemCount);
            items(0).HeapIndex = 0;
            SortDown(items(0));
            return firstItem;
        }

        public void UpdateItem(T item) {
            SortUp(item);
        }

        public int Count {
            get {
                return currentItemCount;
            }
        }

        public bool Contains(T item) {
            return Equals(items(item.HeapIndex), item);
        }

        void SortDown(T item) {
            while (true) {
                int childIndexLeft = item.HeapIndex * 2 + 1;
                int childIndexRight = item.HeapIndex * 2 + 2;
                int swapIndex = 0;

                if (childIndexLeft < currentItemCount) {
                    swapIndex = childIndexLeft;

                    if (childIndexRight < currentItemCount) {
                        if (items(childIndexLeft).CompareTo(items(childIndexRight)) < 0) {
                            swapIndex = childIndexRight;
                        }
                    }

                    if (item.CompareTo(items(swapIndex)) < 0) {
                        Swap(item, items(swapIndex));
                    }
                    else {
                        return;
                    }
                }
                else {
                    return;
                }
            }
        }

        void SortUp(T item) {
            int parentIndex = (item.HeapIndex - 1) / 2;

            while (true) {
                T parentItem = items(parentIndex);
                if (item.CompareTo(parentItem) > 0) {
                    Swap(item, parentItem);
                }
                else {
                    break;
                }

                parentIndex = (item.HeapIndex - 1) / 2;
            }
        }

        void Swap(T itemA, T itemB) {
            items(itemA.HeapIndex) = itemB;
            items(itemB.HeapIndex) = itemA;
            int itemAIndex = itemA.HeapIndex;
            itemA.HeapIndex = itemB.HeapIndex;
            itemB.HeapIndex = itemAIndex;
        }

    }


    public interface IHeapItem : IComparable { 
        int HeapIndex {
            get;
            set;
        }
    }

Grid.cs

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;

    public class Grid : MonoBehaviour {

        public bool onlyDisplayPathGizmos;
        public Transform player;
        public LayerMask unwalkableMask;
        public Vector2 gridWorldSize;
        public float nodeRadius;
        Node(,) grid;

        float nodeDiameter;
        int gridSizeX, gridSizeY;

        void Start() {
            nodeDiameter = nodeRadius * 2;
            gridSizeX = Mathf.RoundToInt(gridWorldSize.x / nodeDiameter);
            gridSizeY = Mathf.RoundToInt(gridWorldSize.y / nodeDiameter);
            CreateGrid();
        }

        public int MaxSize {
            get {
                return gridSizeX * gridSizeY;
            }
        }

        void CreateGrid() {
            grid = new Node(gridSizeX, gridSizeY);
            Vector3 worldBottomLeft = transform.position - Vector3.right * gridWorldSize.x / 2 - Vector3.forward * gridWorldSize.y / 2;

            for (int x = 0; x < gridSizeX; x++) {
                for (int y = 0; y < gridSizeY; y++) {
                    Vector3 worldPoint = worldBottomLeft + Vector3.right * (x * nodeDiameter + nodeRadius) + Vector3.forward * (y * nodeDiameter + nodeRadius);
                    bool walkable = !(Physics.CheckSphere(worldPoint, nodeRadius, unwalkableMask));
                    grid(x, y) = new Node(walkable, worldPoint, x, y);
                }
            }
        }

        public List GetNeighbors(Node node) {
            List neighbors = new List();

            for (int x = -1; x <= 1; x++) {
                for (int y = -1; y <= 1; y++) {
                    if (x == 0 && y == 0)
                        continue;

                    int checkX = node.gridX + x;
                    int checkY = node.gridY + y;

                    if (checkX >= 0 && checkX < gridSizeX && checkY >= 0 && checkY < gridSizeY) {
                        neighbors.Add(grid(checkX, checkY));
                    }
                }
            }

            return neighbors;
        }
        public Node NodeFromWorldPoint(Vector3 worldPosition) {
            float percentX = (worldPosition.x + gridWorldSize.x / 2) / gridWorldSize.x;
            float percentY = (worldPosition.z + gridWorldSize.y / 2) / gridWorldSize.y;
            percentX = Mathf.Clamp01(percentX);
            percentY = Mathf.Clamp01(percentY);

            int x = Mathf.RoundToInt((gridSizeX - 1) * percentX);
            int y = Mathf.RoundToInt((gridSizeY - 1) * percentY);
            return grid(x, y);
        }

        public List path;
        void OnDrawGizmos() {
            Gizmos.DrawWireCube(transform.position, new Vector3(gridWorldSize.x, 1, gridWorldSize.y));

            if (onlyDisplayPathGizmos) {
                if (path != null) {
                    foreach (Node n in path) {
                        Gizmos.color = Color.black;
                        Gizmos.DrawCube(n.worldPosition, Vector3.one * (nodeDiameter - .1f));
                    }
                }
            }
            else {
                if (grid != null) {
                    Node playerNode = NodeFromWorldPoint(player.position);
                    foreach (Node n in grid) {
                        Gizmos.color = (n.walkable) ? Color.white : Color.red;
                        if (path != null)
                            if (path.Contains(n))
                                Gizmos.color = Color.black;
                        Gizmos.DrawCube(n.worldPosition, Vector3.one * (nodeDiameter - .1f));
                    }
                }
            }
        }
    }

Node.cs

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;

    public class Node : IHeapItem {

        public bool walkable;
        public Vector3 worldPosition;
        public int gridX;
        public int gridY;

        public int gCost;
        public int hCost;
        public Node parent;
        int heapIndex;


        public Node(bool _walkable, Vector3 _worldPos, int _gridX, int _gridY) {
            walkable = _walkable;
            worldPosition = _worldPos;
            gridX = _gridX;
            gridY = _gridY;
        }

        public int fCost {
            get {
                return gCost = hCost;
            }
        }

        public int HeapIndex {
            get {
                return heapIndex;
            }
            set {
                heapIndex = value;
            }
        }

        public int CompareTo(Node nodeToCompare) {
            int compare = fCost.CompareTo(nodeToCompare.fCost);
            if (compare == 0) {
                compare = hCost.CompareTo(nodeToCompare.hCost);
            }
            return -compare;
        }

    }

Pathfinding.cs

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using System.Diagnostics;
    public class Pathfinding : MonoBehaviour {

        public Transform seeker, target;

        Grid grid;

        void Awake() {
            grid = GetComponent();
        }

        void Update() {
            FindPath(seeker.position, target.position);
        }

        void FindPath(Vector3 startPos, Vector3 targetPos) {

            Stopwatch sw = new Stopwatch();
            sw.Start();

            Node startNode = grid.NodeFromWorldPoint(startPos);
            Node targetNode = grid.NodeFromWorldPoint(targetPos);

            Heap openSet = new Heap(grid.MaxSize);
            HashSet closedSet = new HashSet();
            openSet.Add(startNode);

            while (openSet.Count > 0) {
                Node currentNode = openSet.RemoveFirst();
                closedSet.Add(currentNode);

                if (currentNode == targetNode) {
                    sw.Stop();
                    print("Path found: " + sw.ElapsedMilliseconds + " ms");
                    RetracePath(startNode, targetNode);
                    return;
                }

                foreach (Node neighbor in grid.GetNeighbors(currentNode)) {
                    if (!neighbor.walkable || closedSet.Contains(neighbor)) {
                        continue;
                    }

                    int newMovementCostToNeighbor = currentNode.gCost + GetDistance(currentNode, neighbor);
                    if (newMovementCostToNeighbor < neighbor.gCost || !openSet.Contains(neighbor)) {
                        neighbor.gCost = newMovementCostToNeighbor;
                        neighbor.hCost = GetDistance(neighbor, targetNode);
                        neighbor.parent = currentNode;

                        if (!openSet.Contains(neighbor))
                            openSet.Add(neighbor);
                    }
                }
            }
        }

        void RetracePath(Node startNode, Node endNode) {
            List path = new List();
            Node currentNode = endNode;

            while (currentNode != startNode) {
                path.Add(currentNode);
                currentNode = currentNode.parent;
            }
            path.Reverse();

            grid.path = path;


        }

        int GetDistance(Node nodeA, Node nodeB) {
            int dstX = Mathf.Abs(nodeA.gridX - nodeB.gridX);
            int dstY = Mathf.Abs(nodeA.gridY - nodeB.gridY);

            if (dstX > dstY)
                return 14 * dstY + 10 * (dstX - dstY);
            return 14 * dstX + 10 * (dstY - dstX);

        }

    }

Unity Seamless Terrain – Stack Exchange for Game Development

I programmatically generate terrain with the terrain object of unity and assign height maps via the terrainData. The problem is that there are also seams when using the GroupingId (which is used for automatic connection).
I even tried to use Neighbors to create a terrain object in the editor and script their terrain data with the seams still in place.

I also tried SetConnectivityDirty after applying terrainData.

Most people who reported this seemed to have (lol) problems with their marginal normals. I can not see this, but if so, how do I go about solving it using Unity Terrains?

If there is no good answer, I have to resort to custom networks and lose all nice terrain tools features.

Enter image description here

Is it possible in Unity to retrieve game objects from an unopened scene?

Excuse my English mistakes, I did my best to make myself understood.

On Unity 2017.1 + C #.

I'm trying to do UnitTest to check for possible errors in the scenes.
and if I want to get the gameObjects from the two different scenes,
I can only get the scene that is currently open in the editor.

How can you solve this problem?
Or is this impossible in the Unity mechanism?

Two seconds I have:

I have two seconds

Hierarchy of Scene 1:

Scene1 hierarchy

Scene2 hierarchy:

Scene2 hierarchy

Code:

Code:

Result: Retrieve only the information of the open scene

Result: Retrieve only the information of the open scene

Unity – Debug this spherecasting scenario

I currently have a problem with my custom drawing controller. I have code that moves the transform.postion.y of a GameObject to simulate gravity, and the ground is detected with SphereCast. SphereCast is thrown down from the middle of the body. And then I have a big cube as a reason.

If I position the character very high above the cube and then press Play, the character is dropped and SphereCast detects a hit (Scenario 1). But if I still position it high above the cube, but not as high as in the first example, the SphereCast will not detect a hit (Scenario 2). So it only recognizes a hit if I start it really high. And this happens only on the first start, because I have a jump function, and if I do the first scenario (impact) and then a jump, the landing after the jump is recognized by SphereCast, even though the jump is the same height as in scenario 2.

My next step is adding a breakpoint in SphereCast Hit while playing Scenario 2 frame by frame. The thing is, if frame by frame, Scenario 2 is detected by SphereCast, so I do not know how to debug this.

Summary:

  • SphereCast reaches the ground when the character is very high above the ground and then presses the play button (Scenario 1)
  • SphereCast does not hit the ground when the character is moderately high above the ground and then presses the play button (Scenario 2)
  • If Scenario 2 runs frame by frame, SphereCast runs
  • Need ideas for debugging