Background info:
So pretty much I started development for a 2D platformer. I have recently (kinda) finnished the first enemy, coding wise. I have a scene set up which is just a basic 11x1 platform for the enemy and player to movearound on. The player moves around just fine, but when the enemy is added something weird happens. Randomly during the runtime the enemy will get stuck at a certain position (Generally near the edge, but not always) and then it for some reason at certain positions it also stops the player from moving past.
For example:
[ 1 ][ 2 ][ 3 ][ 4 ][ 5][ 6 ][ 7 ][ 8 ][ 9 ][ 10 ][ 11 ]
If the enemy randomly got stuck at point 2, the player might get stuck at point 9 when moving right even though the player can still walk over point 9 when walking to the left.
To my knowledge, It’s completly random when / where they get stuck. I know this has something to do with the enemy because when the enemy isn’t active in the scene, the player can move fine.
Enemy Code:
using UnityEngine;
using System.Collections;
public class Icey : MonoBehaviour {
// Enemy Description:
// Name - Icey.
// Walks around at speed 2, but when the player is seen
// He charges at speed 5. If the player moves out of sight
// Icey won't stop charging straight away.
// When he collides with the player, Icey spawns a iceberg
// (Just for visual effects) which kills the player.
// If Icey goes near a drop / cliff,
// He automaticly turns around.
// Refrences
private Transform thisEnemy; // Refers to the transform of this enemy
private Rigidbody2D rb; // The attached rigidbody to Icey.
public GameObject Iceberg; // The object that spawns when Icey collides with player.
public Transform gp_Left; // The left ground point. Detects when near edge of ground.
public Transform gp_Right; // The right ground point. Detects when near edge of ground.
// Vars
private int faceDir; // The dirrection Icey is facing. -1 = Left. 1 = Right.
public float defaultFaceDirCooldown; // Helps when reseting the dirFaceCooldown.
private float faceDirCooldown; // When turning around, stops from changing dir every frame.
public int moveSpeed; // The current speed;
public int defaultSpeed; // The default speed;
public int chargeSpeed; // The speed when Icey charges the player.
public float defaultChargeStopCooldown; // Helps when reseting the ChargeStopCooldown.
private float chargeStopCooldown; // The time it takes before Icey stops charging after the player is out of sight.
public float gp_Radius; // The collision radius for each ground point.
public LayerMask groundMask; // Helps detects which objects are ground objects.
private bool leftGroundSafe; // Set to true if Icey can continue moving left.
private bool rightGroundSafe; // Set to true if Icey can continue moving righ.
private float thisEnemy_Ycentered; // The coords of the vertical center of Icey because the pivot is set to the bottom.
// Use this for initialization
void Start () {
thisEnemy = this.gameObject.transform;
thisEnemy_Ycentered = thisEnemy.position.y;
thisEnemy_Ycentered += 0.5f;
rb = GetComponent<Rigidbody2D>();
moveSpeed = defaultSpeed;
faceDir = -1;
faceDirCooldown = defaultFaceDirCooldown;
chargeStopCooldown = defaultChargeStopCooldown;
}
// Update is called once per frame
void Update () {
Debug.DrawRay(new Vector2(thisEnemy.position.x, thisEnemy_Ycentered), new Vector2(faceDir*10, 0), Color.green);
// Timers //
faceDirCooldown -= Time.deltaTime;
// turnAround function call
leftGroundSafe = Physics2D.OverlapCircle(gp_Left.position, gp_Radius, groundMask); // Detects if the ground points are colliding with ground on the left side of Icey.
rightGroundSafe = Physics2D.OverlapCircle(gp_Right.position, gp_Radius, groundMask); // Detects if the ground points are colliding with ground on the right side of Icey.
if (!leftGroundSafe || !rightGroundSafe)
{
if (faceDirCooldown <= 0)
{
faceDirCooldown = defaultFaceDirCooldown; // resets the cooldown timer.
rb.velocity = Vector2.zero; // Temporary stops all of Icey's movement
faceDir = -faceDir; // Inverses the faceDir.
transform.localScale = new Vector2(-transform.localScale.x, transform.localScale.y);
}
}
// Movement
Vector2 moveDir = new Vector2(faceDir * moveSpeed, rb.velocity.y);
rb.velocity = moveDir;
}
// Used for detecting collisions.
void OnCollisionEnter2D(Collision2D other) {
if (other.gameObject.tag == "Player") {
other.gameObject.GetComponent<playerController>().die(); // Kills the player via a function in the player controller script.
// Is used to offset the ice berg, centered to Icey.
Vector2 localOffset = new Vector2(-0.5f, 0);
Vector2 worldOffset = transform.rotation * localOffset;
Vector2 spawnPosition = (Vector2)transform.position + worldOffset;
Instantiate(Iceberg, spawnPosition, Quaternion.identity); // Spawns the ice berg
}
}
void FixedUpdate() {
RaycastHit2D[] hits = Physics2D.RaycastAll(new Vector2 (thisEnemy.position.x, thisEnemy_Ycentered), new Vector2(faceDir*10, 0));
foreach (RaycastHit2D hit in hits)
{
if (hit.collider.gameObject.tag == "Player"){
moveSpeed = chargeSpeed; // Starts the charge at the player
}
if (hit.collider.gameObject.tag != "Player" && moveSpeed == chargeSpeed) {
chargeStopCooldown -= Time.deltaTime; // Starts the count down before stopping the charge.
if(chargeStopCooldown <= 0) {
moveSpeed = defaultSpeed; // Sets the speed back to default
chargeStopCooldown = defaultChargeStopCooldown; // Resets the timer before Icey can stop charging.
}
}
}
}
// Shows where the ground points are //
void OnDrawGizmos() {
Gizmos.color = Color.green;
Gizmos.DrawWireSphere(gp_Left.position, gp_Radius);
Gizmos.DrawWireSphere(gp_Right.position, gp_Radius);
}
}
Notes:
Naturally everything in the editor is setup. The ground is layered ground, the player is tagged player, all the vars are set up. Also sorry about how the comments kinda get in the way. Regardless of the question, any positive feedback on my code would be nice because I’m new and there are probably many easier ways to write my code / shorten it.
Just to claify:
The question is, Why are the player / enemy randomly stoping and how should I go about fixing it.
Thanks in advance