Search code examples
unity-game-enginecollision-detectioncoroutinelerp

Unity Move 3D object Within a barrier


I am using the code below attached to a cylinder object with ridge body and collision. This object is placed in the middle of collision barriers that form a circle. I am trying to get this object to move smoothly forward a random distance and after it moves, wait a random time and then move again. If it hits the barrier with tag name "wall" then turn around by some degree away from walls so it can continues to move around inside. and keep doing the following code.

However the object doesn't move smoothly, and it barely moves at all.

How can I fix this? Thanks in advance for any links or help to this problem.

public bool hit, m = false;


public float waitTime;
public float movDistance;
public float fRotation;
public float transitionSpeed = 1f;

private float lerpTime = 3f;
private float currentLerpTime = 0f;
private Vector3 startPos, endPos;

void Start()
{
    //rb = GetComponent<Rigidbody>();
    startPos = this.transform.position;
}

private void Update()
{
    if (m == false) {
        if (hit == true) {
            currentLerpTime += Time.deltaTime;
            if (currentLerpTime >= lerpTime) {
                currentLerpTime = lerpTime;
                hit = false;
            }
            float p = currentLerpTime / lerpTime;
            this.transform.position = Vector3.Lerp(startPos, endPos, p);


        }
        if (hit == false) {
            setRanges();
            m = true;
            StartCoroutine(Example());
        }
    }
}

public void setRanges()
{
    waitTime = Random.Range(4f, 10f);
    movDistance = Random.Range(2f, 10f);
    fRotation = Random.Range(1f, 270f);
    endPos = this.transform.position + Vector3.forward * movDistance;
}


IEnumerator Example()
{
    Debug.Log("Wait" + waitTime + "Seconds");
    startPos = this.transform.position;
    yield return new WaitForSeconds(waitTime);
    hit = true;
    m = false;

}
void OnCollisionEnter(Collision col)
{
    if (col.gameObject.tag == "wall")
    {

        Debug.Log(" hit wall");
        this.transform.rotation = Quaternion.Euler(0, 180, 0);
        hit = false;
    }
}

Solution

  • Omit some trivial parts from your code

    if (m == false) {
        if (hit == true) {
            //.... Move
            hit = false;
        }
        if (hit == false) {
            //.... Set new target position
            m = true;
            //.... Set m to false and hit to true after waitTime
        }
    }
    

    And you will find the problem in your logic.

    After the object moves for 1 frame, you set hit to false then it stops move again until waitTime passed.

    I guess the right logic should be stop the object after it reach the target position, so:

    if(hit){
        //... Move
        if(currentLerpTime == lerpTime)
             hit = false;
    }