1
\$\begingroup\$

I've been trying to work an enemy that moves in a circular motion for my RPG game, but for some reason, whenever I press play the GameObject instantly goes hundreds of units in the X and Y coordinates. It also move back to -1 on the Z axis. Here's the script to my enemy's movement:

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

public class EnemyScript : MonoBehaviour
{

    private Rigidbody2D rb;

    [SerializeField]
    float rotationRadius = 2f, angularSpeed = 2f;
    float posX, posY, angle = 0f;

    // Start is called before the first frame update
    void Start()
    {
        // Gets the RigidBody2D component
        rb = GetComponent<Rigidbody2D>();
    }

    // Update is called once per frame
    void Update()
    {
        Movement_1();
    }

    void Movement_1()
    {
        posX = rb.position.x + Mathf.Cos(angle) + rotationRadius;
        posY = rb.position.y + Mathf.Sin(angle) + rotationRadius;
        transform.position = new Vector2(posX, posY);
        angle = angle + Time.deltaTime * angularSpeed;

        if (angle >= 360f)
        {
            angle = 0f;
        }
    }
}
\$\endgroup\$
2
  • \$\begingroup\$ Each frame, you're setting the new position to be a point on a circle centered at your old position. Then next frame, a circle centered on that new position, and so on. So you effectively rocket the object away by one radius every frame. Also, you're using transform.position to move a Rigidbody, which you should avoid unless you're trying to teleport it. \$\endgroup\$
    – DMGregory
    Commented Jan 20, 2021 at 19:16
  • \$\begingroup\$ @DMGregory Ok, I will change transform.position to rb.MovePosition. \$\endgroup\$ Commented Jan 20, 2021 at 19:19

1 Answer 1

1
\$\begingroup\$

You have a double-delta there. You have a delta on the position (you change the position relative to the current position, based on the angle), and you also have a delta on the angle (you change the angle relative to the previous angle). That is equivalent to having the position change every frame, but also having the velocity change every frame.

What you want to do is increase the angle every frame, but the position itself should be set using a formula based on the angle, but not based on the previous position. Only one element that changes relative to itself - the angle.

So something like this:

void Update() {
  angle += Time.deltaTime * angularSpeed; // update angle
  Vector3 direction = Quaternion.AngleAxis(angle, Vector3.forward) * Vector3.up; // calculate direction from center - rotate the up vector Angle degrees clockwise
  transform.position = center + direction * radius; // update position based on center, the direction, and the radius (which is a constant)
}

You could apply the same method and use the sin/cos if you prefer (find the position using sin/cos based on the angle, but don't use the previous position as an input). Personally I find the method above more intuitive.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .