I was working on a 2.5D enemy AI movement on a platform. The idea is to get the enemy(green cubes) to move along the platform, when it gets to the edge of the platform, it turns around and goes the opposite direction, if it meets another enemy, it should turn around and go the opposite direction.
My code works and the enemy moves as I expected on the editor, but when I build it out to mobile, the enemy develops a weird movement(like it is trying to go in both directions at the same time).
Here's a playtest on the editor: https://youtu.be/fmZSHd3GXDE
Here's a playtest on mobile: https://youtu.be/xBDDdgVrGQE
I can't find out what could be the cause. What do you think?
Here is my code:
private Rigidbody mRigidbody = null;
private bool isIdle = true;
private bool turnedLeft = false;
private bool turnedRight = false;
private Transform currentObstacle = null;
private Transform currentPlatformEdge = null;
private Transform leftMostPlatformEdge = null; //transform that represents left end of a platform
private Transform rightMostPlatformEdge = null; //transform that represents the right end of a platform
private int randomNumber = 0;
private float lookDirection = 1f;
[SerializeField] private float walkSpeed = 92f;
[SerializeField] private float gravityMultiplier = 2f;
[SerializeField] private float rayDistanceToObstacle = 1.25f;
private Vector2 right = Vector2.zero;
private void Awake()
{
mRigidbody = GetComponent<Rigidbody>();
}
void Start()
{
randomNumber = Random.Range(0, 2);
currentPlatformEdge = leftMostPlatformEdge;
}
private void FixedUpdate()
{
ApplyGravity();
right = transform.TransformDirection(Vector2.right);
CastRay();
Navigation();
}
private void ApplyGravity()
{
Vector2 extraGravityForce = (Physics.gravity * gravityMultiplier) - Physics.gravity;
mRigidbody.AddForce(extraGravityForce);
}
private void CastRay()
{
Ray ray = new Ray(transform.position, Vector2.right * lookDirection);
Vector2 startPos = transform.position;
startPos.y += 1f;
#region Obstacle Ray
bool HittingObstacle = Physics.Raycast(ray, out RaycastHit obstacleHit, rayDistanceToObstacle);
if (HittingObstacle)
{
if (obstacleHit.collider.CompareTag("Obstacle") || obstacleHit.collider.CompareTag("Enemy")
|| obstacleHit.collider.CompareTag("Platform"))
currentObstacle = obstacleHit.transform;
}
else if (!HittingObstacle && currentPlatformEdge != null)
currentObstacle = null;
#endregion
}
private void Navigation()
{
Vector2 CurrentTargetDistanceFromTransform = Vector2.zero, CurrentPlatformEdgeDistanceFromTransform = Vector2.zero;
if (currentObstacle != null)
CurrentTargetDistanceFromTransform = currentObstacle.position - transform.position;
if (currentPlatformEdge != null)
CurrentPlatformEdgeDistanceFromTransform = currentPlatformEdge.position - transform.position;
if (currentObstacle != null || currentPlatformEdge != null)
{
if (currentObstacle != null) //If an enemy or an object with the obstacle tag is in this transform's way
{
if (Vector2.Dot(right, CurrentTargetDistanceFromTransform) < 0)
WalkLeft();
else
WalkRight();
}
else if (currentPlatformEdge != null && currentObstacle == null)
{
if (Vector2.Dot(right, CurrentPlatformEdgeDistanceFromTransform) < 0)
WalkRight();
else
WalkLeft();
}
}
else
WalkTowardsAnyDirection();
}
private void TurnLeft()
{
Quaternion Rot = Quaternion.Euler(0, -90, 0);
transform.rotation = Rot;
lookDirection = -1;
mRigidbody.velocity = new Vector2(0, mRigidbody.velocity.y);
turnedLeft = true;
turnedRight = false;
}
private void TurnRight()
{
Quaternion Rot = Quaternion.Euler(0, 90, 0);
transform.rotation = Rot;
lookDirection = 1;
mRigidbody.velocity = new Vector2(0, mRigidbody.velocity.y);
turnedRight = true;
turnedLeft = false;
}
private void WalkLeft()
{
isIdle = false;
if (!isIdle)
{
if (!turnedLeft)
TurnLeft();
mRigidbody.velocity = new Vector2(-walkSpeed * Time.fixedDeltaTime, mRigidbody.velocity.y);
}
if (leftMostPlatformEdge != null)
currentPlatformEdge = leftMostPlatformEdge;
else
currentPlatformEdge = null;
}
private void WalkRight()
{
isIdle = false;
if (!isIdle)
{
if (!turnedRight)
TurnRight();
mRigidbody.velocity = new Vector2(walkSpeed * Time.fixedDeltaTime, mRigidbody.velocity.y);
}
if (rightMostPlatformEdge != null)
currentPlatformEdge = rightMostPlatformEdge;
else
currentPlatformEdge = null;
}
protected void WalkTowardsAnyDirection()
{
if (randomNumber == 0)
WalkLeft();
else
WalkRight();
}
private void OnCollisionEnter(Collision collision)
{
if (collision.gameObject.CompareTag("Platform"))
{
leftMostPlatformEdge = collision.gameObject.transform.GetChild(0).transform;
rightMostPlatformEdge = collision.gameObject.transform.GetChild(1).transform;
WalkTowardsAnyDirection();
return;
}
}
private void OnCollisionExit(Collision collision)
{
if (collision.gameObject.CompareTag("Platform"))
{
leftMostPlatformEdge = null;
rightMostPlatformEdge = null;
}
}