1
\$\begingroup\$

enter image description here

So, imagine the drawing in 3d and obstacle is in front of the player, and I do a raycast for checking in front of the player and if the raycast hits the obstacle the player needs to check both left and right and move corresponding to the space it has on the x-axis and if the player has more space on the right then left he moves right and vice versa and the player has the bounds from A-B and the A-B is a Road and the road has mesh collider Please help me. I don't know how to check the space that the player has.

\$\endgroup\$
4
  • 1
    \$\begingroup\$ Can you describe what is not working? \$\endgroup\$ Oct 13 at 13:44
  • \$\begingroup\$ well, i don't know how to calculate the distance between player and the collider ends \$\endgroup\$ Oct 13 at 13:48
  • 1
    \$\begingroup\$ It's not clear to me what behaviour you want to see in game. Try editing your question to include a diagram of a situation that arises in your game and how you want the movement to change in response to that situation. Repeat for as many distinct situations as you need to fully explain the behaviour. \$\endgroup\$
    – DMGregory
    Oct 14 at 13:07
  • \$\begingroup\$ Is the road straight? Do I assume correctly that your diagram above is top down, and player is moving down in the picture (and is not obstructed by the obstacle in this case)? \$\endgroup\$ Oct 14 at 17:21
1
\$\begingroup\$

Edit -- revised to reflect new details from OP

I guess you are looking for something like this: Demo

To calculate the distance to another collider, Physics.Raycast is sufficient.

Here's an example loosely based on code from your original post with cruft removed that isn't related to the task at hand. Assuming we know the width of the road, we can simply cast rays downward at half road width to the right and left of our position. Whichever hits is the side with the most room!

using UnityEngine;
public class CycleController : MonoBehaviour
{

    [SerializeField] private float checkDistance;
    [SerializeField] private float roadWidth;
    [SerializeField] private float moveSpeed;
    [SerializeField] private string obstacleLayer;
    [SerializeField] private string roadLayer;

    Rigidbody rb;
    public int obstacleLayerMask, roadLayerMask;
    Ray rayObstacle, rayRoadLeft, rayRoadRight;

    private void Start()
    {
        rb = GetComponent<Rigidbody>();
        obstacleLayerMask = LayerMask.GetMask(obstacleLayer);
        roadLayerMask = LayerMask.GetMask(roadLayer);
    }

    private void Update()
    {
        //note calculating this every frame only for demo purposes...
        rayObstacle.direction = transform.forward;
        rayObstacle.origin = transform.position;
        rayRoadRight.direction = rayRoadLeft.direction = -transform.up;
        rayRoadRight.origin = transform.position + (transform.right * (roadWidth / 2f));
        rayRoadLeft.origin = transform.position - (transform.right * (roadWidth / 2f));

        Move();
        AIMove();
    }
    private void Move()
    {
        float verticalInput = Input.GetAxis("Vertical") * moveSpeed;                            
        rb.AddRelativeForce(0, 0, verticalInput, ForceMode.Force);                       
    }


    private void AIMove()
    {
        RaycastHit hitInfo;
       if(Physics.Raycast(rayObstacle, out hitInfo, checkDistance, obstacleLayerMask))
        {
            Debug.LogFormat("There is an obstacle named {0} {1:N2} units in front", hitInfo.collider.name, hitInfo.distance);

            if (Physics.Raycast(rayRoadLeft, out hitInfo, 10, roadLayerMask))
            {
                Debug.Log("there's room on the left!");
            }
            else
            {
                Debug.Log("there's no room on the left!");
            }

            if (Physics.Raycast(rayRoadRight, out hitInfo, 10, roadLayerMask))
            {
                Debug.Log("there's room on the right!");
            }
            else
            {
                Debug.Log("there's no room on the right!");
            }
        }
    }


    private void OnDrawGizmosSelected()
    {
        Gizmos.color = Color.green; // green ray checks for obstacles
        Gizmos.DrawRay(transform.position, rayObstacle.direction * checkDistance);

        Gizmos.color = Color.red; // red ray checks for road below
        Gizmos.DrawRay(rayRoadLeft.origin, rayRoadLeft.direction * 10);
        Gizmos.DrawRay(rayRoadRight.origin, rayRoadRight.direction * 10);
    }
}

First up, we're creating some layer masks so our Raycasts will only return hits on the objects we care about. LayerMask.GetMask does the bit twiddling for us. In Update I'm updating the rays for forward (obstacle collision) and downward left and right, largely because we are also using these rays to draw representations in OnDrawGizmosSelected. In OnAIMove we cast the obstacle ray out to the distance we care about. If it hits something it'll return true, and the passed RaycastHit hitInfo will be filled with useful information about what we hit, including how far away it is. At this point we'll cast two rays downward, to the left and right of our position. Since these distances are half the width of the road, only one cast will succeed if we are to the left or right already. (I'll leave it up to you to decide what to do if the player is exactly in the middle).

Here's the scene in play mode. green ray is for obstacle detection, red rays are for road detection. scene view The game view. game view Console output. console output The player config in the inspector. Layer mask ints are only exposed as public for debugging; these are computed by LayerMask.GetMask as related above. player config in inspector This is the scene hierarchy. scene hierarchy

\$\endgroup\$
7
  • \$\begingroup\$ Thanks a lot that's the exact representation of the problem. \$\endgroup\$ Oct 15 at 2:47
  • \$\begingroup\$ Thanks for taking time to explain in detail with pictures \$\endgroup\$ Oct 15 at 11:12
  • \$\begingroup\$ But what if the width of the road is non-uniform like a curve, how to check the width?? \$\endgroup\$ Oct 15 at 14:40
  • \$\begingroup\$ assuming the player/ vehicle is following the curvature road, it should still work just fine -- the downward cast rays are relative to the player's orientation and position \$\endgroup\$ Oct 15 at 15:01
  • \$\begingroup\$ what if an obstacle is in middle of road both rays are hitting then wired jiggle is happening \$\endgroup\$ Oct 16 at 8:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.