- Home /
2D Platformer Ai Movement Decision Making Problems
!! NEED SOME ADVICE ON MY AI SCRIPT !!
I have procedually generated levels in a 2d platformer game, and I spawn 'bots' at random locations at random times throughout the level after runtime.
I would like the 'bots' to move around the level reasonably freely, and stop and attack either the player or each other when in range of their raycasts. They do most of this and also jump up and down platforms. They walk left and right properly and idle when they want, so that's all working properly. The real trouble I'm having is with climbing the ladders.
I would like them to get on and off the ladders when there's a platform next to them or either decide to keep climbing up or down, if there is an up or down ladder part left.
Most of that they accomplish but its quite buggy. They sometimes overshoot a platform or ladder and keep walking or they get stuck when climbing onto or off ladders sometimes. Also sometimes they'll go to climb onto a ladder and then jump straight back off which is annoying as I would like them to be more fluid.
I think they get a little confused sometimes.
Anyway, my code sorta works so what I would like is if somebody nice that knew a bit about ai 'bot' like movement could go over my code and give me a few pointers on all the things I've done wrong and could do better. Or a better way to decide what next action to take.
And just generally would like an experienced person to tell me how horrible my code practices are, as I have only been coding for about 8 months now, working on various failed projects and learning heaps.
Anyway, the code is as follows, some of it is just commented out because things seem to work better without having to many methods changing bools all the time.
I try using bools like switches to change between one action or another, or interrupt that action in progress. Any help or advice is good advice so please give me some feedback.
using UnityEngine;
using System.Collections;
public class Enemy_Control : MonoBehaviour
{
// raycast for walking.
private RaycastHit2D isPlatLeft, isPlatRight;
// basic movement vars
public float walkSpeed = 500f;
public float deAcceleration = 1000f, fallAcceleration = -30f;
public Vector2 gravity = new Vector2 (0, -30f);
public float climbLadderSpeed = 300;
private float fallSpeed = -30;
// for action wait times
private float waitMin = 20f, waitMax = 200f, waitCounter, waitCounterMax;
// for starting the action timer and deciding. for walk or idle.
private bool startWaitTimer = true, decided = false;
private int deciderInt;
private bool isFacingRight = true;
private bool walkLeft = false, walkRight = false, idle = false;
public static bool walkinLeft = false, walkinRight = false;
private bool platToLeft, platToRight;
protected Animator animator;
private bool isOnLadder = false;
// grounded stuff
private RaycastHit2D onGround;
private bool isGrounded = false;
// shooting stuff
public float gunRange = 10f, shootTimerMax = 18f;
private bool hasAimLeft = false, hasAimRight = false;
private RaycastHit2D aimerLeft, aimerRight;
private bool shooting = false;
public GameObject bulletLeft, bulletRight, muzzleFlashLeft, muzzleFlashRight;
private float shootTimer = 0f ;
public Vector2 bulletLeftOffset, bulletRightOffset;
// for jumping
private bool jumpLeft = false, jumpRight = false;
private bool isJumping = false;
public float jumpStrength = 200f;
private RaycastHit2D jumpCheckLeft, jumpCheckRight;
// just for changing directions when running into a platform face first.
private RaycastHit2D changeDirCheckLeft, changeDirCheckRight;
// for ladders
private int waypointDirChoice;
private bool climbDown = false, climbUp = false;
private RaycastHit2D laddCheckLeft, laddCheckRight;
private bool laddPlatToLeft = false, laddPlatToRight = false;
private bool doWaypointOnce = false;
private int rann, rand, bob, bill;
// for death
public bool enemyDies = false;
private bool disableAllMovement = false;
// Use this for initialization
void Start ()
{
animator = GetComponent<Animator> ();
waitCounterMax = Random.Range (waitMin, waitMax);
startWaitTimer = true;
isOnLadder = false;
}
void WalkIdleDecider ()
{
// THIS ALL FIRES ONCE EVERY TIME THE WAITCOUNTER IS OVER THE WAITCONTERMAX.
if (disableAllMovement == false) {
// main decider
if (decided == false) {
deciderInt = Random.Range (0, 3);
bob = Random.Range (0, 2);
decided = true;
}
// for idle
if (deciderInt == 0) {
idle = true;
walkLeft = false;
walkRight = false;
} else {
decided = false;
idle = false;
}
// for walk left
if (deciderInt == 1) {
if (platToLeft) {
walkLeft = true;
walkRight = false;
} else {
waitCounter = waitCounterMax;
decided = false;
walkLeft = false;
}
}
// for walk right
if (deciderInt == 2) {
if (platToRight) {
walkRight = true;
walkLeft = false;
} else {
waitCounter = waitCounterMax;
decided = false;
walkRight = false;
}
}
}
}
void LadderDecider ()
{
// THIS ALL FIRES ONCE EVERY TIME THE WAITCOUNTER IS OVER THE WAITCONTERMAX.
if (isOnLadder) { // if on a ladder, what direction should i go?
// if grounded then climb up to next.
rann = Random.Range (0, 2);
rand = Random.Range (0, 2);
bob = Random.Range (0, 2);
bill = Random.Range (0, 2);
if (isGrounded) {
climbUp = true;
} else {
int ran = Random.Range (0, 2);
if (ran == 0) {
climbUp = true;
climbDown = false;
}
if (ran == 1) {
climbDown = true;
climbUp = false;
}
}
}
}
// Update is called once per frame
void Update ()
{
if (disableAllMovement == false) {
// if (isOnLadder == false) {
// raycasting for checking stuff. Will need more raycasts for other things here.
isPlatLeft = Physics2D.Raycast (new Vector2 (transform.position.x - 1f, transform.position.y), new Vector2 (0, -1), 8f);
isPlatRight = Physics2D.Raycast (new Vector2 (transform.position.x + 1f, transform.position.y), new Vector2 (0, -1), 8f);
Debug.DrawRay (new Vector2 (transform.position.x - 1f, transform.position.y), new Vector2 (0, -1), Color.red);
Debug.DrawRay (new Vector2 (transform.position.x + 1f, transform.position.y), new Vector2 (0, -1), Color.red);
//}
// for if grounded.
onGround = Physics2D.Raycast (new Vector2 (transform.position.x, transform.position.y - 0.5f), new Vector2 (0, -1), 0.3f);
Debug.DrawRay (new Vector2 (transform.position.x, transform.position.y - 0.5f), new Vector2 (0, -1), Color.blue);
if (isOnLadder == false) {
// for aiming
aimerLeft = Physics2D.Raycast (new Vector2 (transform.position.x - 0.5f, transform.position.y), new Vector2 (-1, 0), gunRange);
aimerRight = Physics2D.Raycast (new Vector2 (transform.position.x + 0.5f, transform.position.y), new Vector2 (1, 0), gunRange);
// for jumping over stuff
jumpCheckLeft = Physics2D.Raycast (new Vector2 (transform.position.x - 0.5f, transform.position.y), new Vector2 (-1, 0), 0.25f);
jumpCheckRight = Physics2D.Raycast (new Vector2 (transform.position.x + 0.5f, transform.position.y), new Vector2 (1, 0), 0.25f);
Debug.DrawRay (new Vector2 (transform.position.x - 0.5f, transform.position.y), new Vector2 (-1, 0), Color.yellow);
Debug.DrawRay (new Vector2 (transform.position.x + 0.5f, transform.position.y), new Vector2 (1, 0), Color.yellow);
}
// for change of direction when running into a platform.
changeDirCheckLeft = Physics2D.Raycast (new Vector2 (transform.position.x - 0.5f, transform.position.y), new Vector2 (-1, 0), 0.1f);
changeDirCheckRight = Physics2D.Raycast (new Vector2 (transform.position.x + 0.5f, transform.position.y), new Vector2 (1, 0), 0.1f);
// for determining when to get off a ladder
laddCheckLeft = Physics2D.Raycast (new Vector2 (transform.position.x - 0.75f, transform.position.y - 1.25f), new Vector2 (-1, 0), 1.5f);
laddCheckRight = Physics2D.Raycast (new Vector2 (transform.position.x + 0.75f, transform.position.y - 1.25f), new Vector2 (1, 0), 1.5f);
Debug.DrawRay (new Vector2 (transform.position.x - 0.75f, transform.position.y - 1.25f), new Vector2 (-1, 0), Color.green);
Debug.DrawRay (new Vector2 (transform.position.x + 0.75f, transform.position.y - 1.25f), new Vector2 (1, 0), Color.green);
// check if a platform is under the player and off to the left.
if (laddCheckLeft) {
if (laddCheckLeft.transform.tag == "PLATFORM" || laddCheckLeft.transform.tag == "LaddCollider") {
int rane = Random.Range (0, 40);
if (rane == 1) {
laddPlatToLeft = true;
}
} else {
laddPlatToLeft = false;
}
} else {
laddPlatToLeft = false;
}
// check if a platform is under the player and off to the right.
if (laddCheckRight) {
if (laddCheckRight.transform.tag == "PLATFORM" || laddCheckRight.transform.tag == "LaddCollider") {
int rane = Random.Range (0, 40);
if (rane == 1) {
laddPlatToRight = true;
}
} else {
laddPlatToRight = false;
}
} else {
laddPlatToRight = false;
}
// check if there is something and check if it is a platform. Can add ladder checks here too.
if (isPlatLeft) {
if (isPlatLeft.transform.tag == "PLATFORM" || isPlatLeft.transform.tag == "GEM" || isPlatLeft.transform.tag == "LaddCollider") {
platToLeft = true;
} else {
platToLeft = false;
}
} else {
platToLeft = false;
}
// check if there is something and check if it is a platform. Can add ladder checks here too.
if (isPlatRight) {
if (isPlatRight.transform.tag == "PLATFORM" || isPlatRight.transform.tag == "GEM" || isPlatRight.transform.tag == "LaddCollider") {
platToRight = true;
} else {
platToRight = false;
}
} else {
platToRight = false;
}
if (waitCounter == 0) {
startWaitTimer = true;
}
// the most important thing. THE ACTION WAIT TIMER.
if (startWaitTimer) {
waitCounter += 1;
}
// this decides how long before making a new decision. As long as its not shooting. Or on a ladder.
if (waitCounter >= waitCounterMax && shooting == false && isOnLadder == false) {
startWaitTimer = false; // stop timer
decided = false; // reset
walkLeft = false; // reset
walkRight = false; // reset
waitCounterMax = Random.Range (waitMin, waitMax);
waitCounter = 0;
WalkIdleDecider ();
}
if (waitCounter >= waitCounterMax && isOnLadder) {
startWaitTimer = false;
climbUp = false;
climbDown = false;
doWaypointOnce = false;
waitCounterMax = Random.Range (waitMin, waitMax);
waitCounter = 0;
LadderDecider ();
}
// check if there is a platform underneath the character.
if (onGround) {
if (onGround.transform.tag == "PLATFORM") {
isGrounded = true;
}
} else {
isGrounded = false;
}
// makes you fall faster if not on ground or ladder.
if (isGrounded == false && isOnLadder == false) {
fallSpeed = fallAcceleration;
climbUp = false;// NEW
climbDown = false;// NEW
}
rigidbody2D.AddForce (new Vector2 (0, fallSpeed));
// just for falling speed.
if (isOnLadder) {
fallSpeed = 0;
}
if (climbUp) {
startWaitTimer = true;
rigidbody2D.velocity = new Vector2 (0, 1f * climbLadderSpeed * Time.deltaTime);
climbUp = true;
climbDown = false;
walkRight = false;
walkLeft = false;
}
if (climbDown) {
startWaitTimer = true;
rigidbody2D.velocity = new Vector2 (0, -1f * climbLadderSpeed * Time.deltaTime);
climbDown = true;
climbUp = false;
walkLeft = false;
walkRight = false;
}
if (isOnLadder && waypointCollided == false) { // is grounded is optional me thinks
if (rand == 0) { // for going up
if (laddPlatToLeft || laddPlatToRight) {
if (laddPlatToLeft) {
if (rann == 0) {
startWaitTimer = true;
//rigidbody2D.AddForce (new Vector2 (-0.5f * walkSpeed * Time.deltaTime, rigidbody2D.velocity.y / 20), ForceMode2D.Impulse);
transform.position += new Vector3 (-0.75f, 0, 0);
}
if (rann == 1) {
waitCounter = waitCounterMax; // redecide
}
}
if (laddPlatToRight) {
if (rann == 0) {
startWaitTimer = true;
//rigidbody2D.AddForce (new Vector2 (0.5f * walkSpeed * Time.deltaTime, rigidbody2D.velocity.y / 20), ForceMode2D.Impulse);
transform.position += new Vector3 (0.75f, 0, 0);
}
if (rand == 1) {
waitCounter = waitCounterMax; // redecide
}
}
} else if (laddPlatToLeft == false || laddPlatToRight == false) {
startWaitTimer = true;
rigidbody2D.velocity = new Vector2 (0, 1f * climbLadderSpeed * Time.deltaTime);
climbUp = true;
}
}
if (rand == 1) { // for going down
if (laddPlatToRight || laddPlatToLeft) {
if (laddPlatToLeft) {
if (rann == 0) {
startWaitTimer = true;
// rigidbody2D.AddForce (new Vector2 (-0.5f * walkSpeed * Time.deltaTime, rigidbody2D.velocity.y / 20), ForceMode2D.Impulse);
transform.position += new Vector3 (-0.75f, 0, 0);
}
if (rand == 1) {
waitCounter = waitCounterMax; // redecide}
}
}
if (laddPlatToRight) {
if (rann == 0) {
startWaitTimer = true;
//rigidbody2D.AddForce (new Vector2 (0.5f * walkSpeed * Time.deltaTime, rigidbody2D.velocity.y / 20), ForceMode2D.Impulse);
transform.position += new Vector3 (0.75f, 0, 0);
}
if (rand == 1) {
waitCounter = waitCounterMax; // redecide}
}
}
}
// climb down
if (laddPlatToLeft == false || laddPlatToRight == false) {
startWaitTimer = true;
rigidbody2D.velocity = new Vector2 (0, -1f * climbLadderSpeed * Time.deltaTime);
climbDown = true;
}
}
}
/*
// if something happens while climbing the ladder then redecide
if (isOnLadder) {
if (laddPlatToLeft) {
startWaitTimer = true;
//rigidbody2D.AddForce (new Vector2 (-0.5f * walkSpeed * Time.deltaTime, rigidbody2D.velocity.y / 20), ForceMode2D.Impulse);
transform.position += new Vector3 (-0.5f, 0, 0);
} else
if (laddPlatToRight) {
startWaitTimer = true;
// rigidbody2D.AddForce (new Vector2 (0.5f * walkSpeed * Time.deltaTime, rigidbody2D.velocity.y / 20), ForceMode2D.Impulse);
transform.position += new Vector3 (0.5f, 0, 0);
}
}
*/
// if grounded and a ladder comes along...
if (isGrounded || isGrounded == false) {
if (walkLeft || walkRight) {
if (isOnLadder) {
if (walkLeft) {
if (isGrounded) {
startWaitTimer = true;
rigidbody2D.velocity = new Vector2 (0, 1f * climbLadderSpeed * Time.deltaTime);
climbUp = true;
walkLeft = false;
} else if (isGrounded == false && waypointCollided == false) {
if (bob == 0) { // climb up
startWaitTimer = true;
rigidbody2D.velocity = new Vector2 (0, 1f * climbLadderSpeed * Time.deltaTime);
climbUp = true;
walkLeft = false;
}
if (bob == 1) { // climb down
startWaitTimer = true;
rigidbody2D.velocity = new Vector2 (0, -1f * climbLadderSpeed * Time.deltaTime);
climbDown = true;
walkLeft = false;
}
}
}
if (walkRight) {
if (isGrounded) {
startWaitTimer = true;
rigidbody2D.velocity = new Vector2 (0, 1f * climbLadderSpeed * Time.deltaTime);
climbUp = true;
walkRight = false;
} else if (isGrounded == false && waypointCollided == false) {
if (bob == 0) { // climb down
startWaitTimer = true;
rigidbody2D.velocity = new Vector2 (0, -1f * climbLadderSpeed * Time.deltaTime);
walkRight = false;
climbDown = true;
}
if (bob == 1) { // climb up
startWaitTimer = true;
rigidbody2D.velocity = new Vector2 (0, 1f * climbLadderSpeed * Time.deltaTime);
walkRight = false;
climbUp = true;
}
}
}
}
}
}
// FOR WAYPOINT COLLISIONS AND WHAT TO DO //
if (waypointCollided && platToLeft || waypointCollided && laddPlatToLeft || waypointCollided) {
if (doWaypointOnce == false) {
bill = Random.Range (0, 2);
doWaypointOnce = true;
}
if (bill == 0) {
// rigidbody2D.AddForce (new Vector2 (-1f * walkSpeed * Time.deltaTime, rigidbody2D.velocity.y / 20), ForceMode2D.Impulse);
transform.position += new Vector3 (0.75f, 0, 0);
climbUp = false;
climbDown = false;
}
if (bill == 1) {
startWaitTimer = true;
rigidbody2D.velocity = new Vector2 (0, -1f * climbLadderSpeed * Time.deltaTime);
climbDown = true;
climbUp = false;
}
}
if (waypointCollided && platToRight || waypointCollided && laddPlatToRight || waypointCollided) {
if (doWaypointOnce == false) {
bill = Random.Range (0, 2);
doWaypointOnce = true;
}
if (bill == 0) {
//rigidbody2D.AddForce (new Vector2 (1f * walkSpeed * Time.deltaTime, rigidbody2D.velocity.y / 20), ForceMode2D.Impulse);
climbUp = false;
climbDown = false;
transform.position += new Vector3 (0.75f, 0f, 0);
}
if (bill == 1) {
startWaitTimer = true;
rigidbody2D.velocity = new Vector2 (0, -1f * climbLadderSpeed * Time.deltaTime);
climbUp = false;
climbDown = true;
}
}
/*
// need this
if (isOnLadder && walkLeft && isGrounded) {
int ran = Random.Range (0, 2);
if (ran == 0 && platToLeft || ran == 0 && laddPlatToLeft) {
walkLeft = true;
climbUp = false;
climbDown = false;
} else {
ran = 1;
}
if (ran == 1) {
walkLeft = false;
waitCounter = waitCounterMax;
}
}
// need this
if (isOnLadder && walkRight && isGrounded) {
int ran = Random.Range (0, 2);
if (ran == 0 && platToRight || ran == 0 && laddPlatToRight) {
walkRight = true;
climbUp = false;
climbDown = false;
} else {
ran = 1;
}
if (ran == 1) {
walkRight = false;
waitCounter = waitCounterMax;
}
}
*/
// FOR STEPPING OFF LADDER HALF WAY UP //
/*
if (walkLeft && stepOffLaddaLeft && climbUp == true || walkLeft && stepOffLaddaLeft && climbUp == false || walkLeft && stepOffLaddaLeft && climbDown == true || walkLeft && stepOffLaddaLeft && climbDown == false) {
if (platToLeft == true || laddPlatToLeft == true) {
rigidbody2D.velocity = (new Vector2 (-1.5f * walkSpeed * Time.deltaTime, rigidbody2D.velocity.y));
climbUp = false;
climbDown = false;
startWaitTimer = true;
// stepOffLaddaLeft = false;
}
}
if (walkRight && stepOffLaddaRight && climbUp == true || walkRight && stepOffLaddaRight && climbUp == false || walkRight && stepOffLaddaRight && climbDown == true || walkRight && stepOffLaddaRight && climbDown == false) {
if (platToRight == true || laddPlatToRight == true) {
rigidbody2D.velocity = (new Vector2 (1.5f * walkSpeed * Time.deltaTime, rigidbody2D.velocity.y));
climbUp = false;
climbDown = false;
startWaitTimer = true;
//stepOffLaddaRight = false;
}
}
*/
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! //
/*
if (isOnLadder && isGrounded && climbDown) {
climbDown = false;
climbUp = true;
startWaitTimer = true;
laddDecider = false;
}
*/
/*
if (isOnLadder && climbUp == false && climbDown == false) {
rigidbody2D.velocity = new Vector2 (0, 0);
}
*/
/*
if (isOnLadder && isGrounded && rigidbody2D.velocity == new Vector2 (0, 0) ) {
climbDown = false;
startWaitTimer = false;
laddDecider = false;
waitCounterMax = Random.Range (waitMin, waitMax);
waitCounter = 0;
LadderDecider ();
}
*/
/*
// this is to try and stop em from falling off the platforms. Don't think it works much
if (walkLeft && platToLeft == false) {
walkLeft = false;
decided = false;
waitCounter = waitCounterMax;
}
if (walkRight && platToRight == false) {
walkRight = false;
decided = false;
waitCounter = waitCounterMax;
}
if (walkLeft && laddPlatToLeft == false) {
walkLeft = false;
decided = false;
waitCounter = waitCounterMax;
}
if (walkRight && laddPlatToRight == false) {
walkRight = false;
decided = false;
waitCounter = waitCounterMax;
}
*/
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! //
/*
// if run into another enemy or player then change direction.
if (isPlatLeft) {
if (isPlatLeft.transform.tag == "Enemy" || isPlatLeft.transform.tag == "Player") {
// waitCounter = waitCounterMax;
platToLeft = true;
} else {
platToLeft = false;
}
} else {
platToLeft = false;
}
// if run into another enemy or player then change direction.
if (isPlatRight) {
if (isPlatRight.transform.tag == "Enemy" || isPlatRight.transform.tag == "Player") {
// waitCounter = waitCounterMax;
platToRight = true;
} else {
platToRight = false;
}
} else {
platToRight = false;
}
*/
// Extra change direction controls //
/* if (changeDirCheckLeft) {
if (changeDirCheckLeft.transform.tag == "PLATFORM" || changeDirCheckLeft.transform.tag == "Enemy" || changeDirCheckLeft.transform.tag == "Player") {
changeDirAtLeft = true;
} else {
changeDirAtLeft = false;
}
}
if (changeDirAtLeft) {
decided = false;
waitCounter = waitCounterMax;
changeDirAtLeft = false;
}
if (changeDirCheckRight) {
if (changeDirCheckRight.transform.tag == "PLATFORM" || changeDirCheckRight.transform.tag == "Enemy" || changeDirCheckRight.transform.tag == "Player") {
changeDirAtRight = true;
} else {
changeDirAtRight = false;
}
}
if (changeDirAtRight && isOnLadder == false) {
decided = false;
waitCounter = waitCounterMax;
changeDirAtRight = false;
}
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! //
*/
if (jumpCheckLeft && isOnLadder == false) {
if (jumpCheckLeft.transform.tag == "PLATFORM") {
if (isGrounded && isJumping == false && isFacingRight == false && isOnLadder == false) {
jumpLeft = true;
}
}
}
if (jumpCheckRight && isOnLadder == false) {
if (jumpCheckRight.transform.tag == "PLATFORM") {
if (isGrounded && isJumping == false && isFacingRight && isOnLadder == false) {
jumpRight = true;
}
}
}
if (jumpLeft) {
isJumping = true;
rigidbody2D.AddForce (new Vector2 (-jumpStrength / 2, 1 * jumpStrength));
walkLeft = true;
jumpLeft = false;
}
if (jumpRight) {
isJumping = true;
rigidbody2D.AddForce (new Vector2 (jumpStrength / 2, 1 * jumpStrength));
walkRight = true;
jumpRight = false;
}
if (isGrounded) {
isJumping = false;
}
/*
// if theres no platform all of a sudden then redecide. And its not shooting.
if (walkLeft && isPlatLeft == false && shooting == false && isOnLadder == false) {
platToLeft = false;
decided = false;
// waitCounter = waitCounterMax;
}
// if theres no platform all of a sudden then redecide. And its not shooting.
if (walkRight && isPlatRight == false && shooting == false && isOnLadder == false) {
platToRight = false;
decided = false;
//waitCounter = waitCounterMax;
}
*/
// NEW STUFF //
/*
// this is for walking left
if (walkLeft && laddPlatToLeft && shooting == false) {
rigidbody2D.velocity = (new Vector2 (-2 * walkSpeed * Time.deltaTime, rigidbody2D.velocity.y));
isFacingRight = false;
startWaitTimer = true;
// if have walked for the full amount of time then redecide.
if (waitCounter >= waitCounterMax) {
walkLeft = false;
decided = false;
laddDecider = false;
}
// if theres no platform to the left then do redecide. And its not shooting.
} else if (walkLeft && laddPlatToLeft == false && shooting == false) {
startWaitTimer = true;
walkLeft = false;
decided = false;
laddDecider = false;
}
// !!!!!!!!!!!!!! //
*/
// this is for walking left
if (walkLeft && platToLeft && shooting == false && isOnLadder == false) {
rigidbody2D.velocity = (new Vector2 (-1 * walkSpeed * Time.deltaTime, rigidbody2D.velocity.y));
isFacingRight = false;
startWaitTimer = true;
climbDown = false;
climbUp = false;
} else {
walkLeft = false;
}
// this is for walking right
if (walkRight && platToRight && shooting == false && isOnLadder == false) {
rigidbody2D.velocity = (new Vector2 (1 * walkSpeed * Time.deltaTime, rigidbody2D.velocity.y));
isFacingRight = true;
startWaitTimer = true;
climbDown = false;
climbUp = false;
} else {
walkRight = false;
}
// if decided to be idle. this is the idle state. As long as its not shooting or on ladder.
if (idle && shooting == false && isOnLadder == false) {
startWaitTimer = true;
rigidbody2D.velocity = new Vector3 (0, 0, 0);
climbUp = false;
climbDown = false;
// must be idle for this to be active I think.
if (rigidbody2D.velocity.x <= -1) {
rigidbody2D.AddForce (new Vector2 (deAcceleration * Time.deltaTime, 0));
}
if (rigidbody2D.velocity.x >= 1) {
rigidbody2D.AddForce (new Vector2 (-deAcceleration * Time.deltaTime, 0));
}
} else {
idle = false;
}
// NEW STUFF //
/*
if (walkRight && laddPlatToRight && shooting == false) {
rigidbody2D.velocity = (new Vector2 (2 * walkSpeed * Time.deltaTime, rigidbody2D.velocity.y));
isFacingRight = true;
startWaitTimer = true;
// if have walked for the full amount of time then redecide.
if (waitCounter >= waitCounterMax) {
walkRight = false;
decided = false;
laddDecider = false;
}
// if theres no platform to the right then do redecide. And its not shooting
} else if (walkRight && laddPlatToRight == false && shooting == false) {
startWaitTimer = true;
walkRight = false;
decided = false;
laddDecider = false;
}
// !!!!!!!!!!!!!!!!!!!!! //
*/
/*
if (climbDown && isOnLadder && laddPlatToLeft == false && laddPlatToRight == false) {
startWaitTimer = true;
rigidbody2D.velocity = new Vector2 (0, 1f * -climbLadderSpeed * Time.deltaTime);
}
if (climbUp && isOnLadder && laddPlatToLeft == false && laddPlatToRight == false) {
startWaitTimer = true;
rigidbody2D.velocity = new Vector2 (0, 1f * climbLadderSpeed * Time.deltaTime);
}
*/
// if is facing right and you shoot me then i'll turn around and take aim.
if (isFacingRight && gotShot && hasAimRight == false) {
// turn around
rigidbody2D.velocity = new Vector2 (-0.1f, 0);
}
// if is facing left and you shoot me then i'll turn around and take aim.
if (isFacingRight == false && gotShot && hasAimLeft == false) {
// turn around
rigidbody2D.velocity = new Vector2 (0.1f, 0);
}
// FOR SHOOTING //
// if got aim
if (aimerLeft) {
if (aimerLeft.transform.tag == "Player" || aimerLeft.transform.tag == "Enemy") {
hasAimLeft = true;
hasAimRight = false;
isFacingRight = false;
} else {
hasAimLeft = false;
}
} else {
hasAimLeft = false;
}
// if got aim
if (aimerRight) {
if (aimerRight.transform.tag == "Player" || aimerRight.transform.tag == "Enemy") {
hasAimRight = true;
hasAimLeft = false;
isFacingRight = true;
} else {
hasAimRight = false;
}
} else {
hasAimRight = false;
}
if (shootTimer >= shootTimerMax) {
shooting = false;
shootTimer = 0;
}
if (hasAimLeft && isFacingRight == false && isOnLadder == false) {
shooting = true;
shootTimer += 1;
// start animation here
if (shootTimer >= shootTimerMax) {
Instantiate (muzzleFlashLeft, new Vector2 (transform.position.x + bulletLeftOffset.x, transform.position.y + bulletLeftOffset.y), Quaternion.identity);
Instantiate (bulletLeft, new Vector2 (transform.position.x + bulletLeftOffset.x, transform.position.y + bulletLeftOffset.y), Quaternion.identity);
shooting = false;
shootTimer = 0;
waitCounter = waitCounterMax;
}
}
if (hasAimRight && isFacingRight && isOnLadder == false) {
shooting = true;
shootTimer += 1;
// start animation here
if (shootTimer >= shootTimerMax) {
Instantiate (muzzleFlashRight, new Vector2 (transform.position.x + bulletRightOffset.x, transform.position.y + bulletRightOffset.y), Quaternion.identity);
Instantiate (bulletRight, new Vector2 (transform.position.x + bulletRightOffset.x, transform.position.y + bulletRightOffset.y), Quaternion.identity);
shooting = false;
shootTimer = 0;
waitCounter = waitCounterMax;
}
}
if (shooting && waitCounter >= waitCounterMax) {
shooting = false;
decided = false;
shootTimer = 0;
}
if (hasAimLeft == false && hasAimRight == false) {
shooting = false;
}
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! //
// ANIMATION DATA //
if (rigidbody2D.velocity == new Vector2 (0, 0) && isFacingRight && isOnLadder == false && shooting == false) {
animator.SetBool ("IdleRight", true);
animator.SetBool ("IdleLeft", false);
animator.SetBool ("RunRight", false);
animator.SetBool ("RunLeft", false);
animator.SetBool ("ClimbIdle", false);
animator.SetBool ("Climb", false);
animator.SetBool ("ShootRight", false);
animator.SetBool ("ShootLeft", false);
animator.SetBool ("RunShootRight", false);
animator.SetBool ("RunShootLeft", false);
}
if (rigidbody2D.velocity == new Vector2 (0, 0) && isFacingRight == false && isOnLadder == false && shooting == false) {
animator.SetBool ("IdleRight", false);
animator.SetBool ("IdleLeft", true);
animator.SetBool ("RunRight", false);
animator.SetBool ("RunLeft", false);
animator.SetBool ("ClimbIdle", false);
animator.SetBool ("Climb", false);
animator.SetBool ("ShootRight", false);
animator.SetBool ("ShootLeft", false);
animator.SetBool ("RunShootRight", false);
animator.SetBool ("RunShootLeft", false);
}
if (rigidbody2D.velocity.x > 0 && isOnLadder == false && shooting == false) {
animator.SetBool ("IdleRight", false);
animator.SetBool ("IdleLeft", false);
animator.SetBool ("RunRight", true);
animator.SetBool ("RunLeft", false);
animator.SetBool ("ClimbIdle", true);
animator.SetBool ("Climb", false);
animator.SetBool ("ShootRight", false);
animator.SetBool ("ShootLeft", false);
animator.SetBool ("RunShootRight", false);
animator.SetBool ("RunShootLeft", false);
}
if (rigidbody2D.velocity.x < 0 && isOnLadder == false && shooting == false) {
animator.SetBool ("IdleRight", false);
animator.SetBool ("IdleLeft", false);
animator.SetBool ("RunRight", false);
animator.SetBool ("RunLeft", true);
animator.SetBool ("ClimbIdle", false);
animator.SetBool ("Climb", false);
animator.SetBool ("ShootRight", false);
animator.SetBool ("ShootLeft", false);
animator.SetBool ("RunShootRight", false);
animator.SetBool ("RunShootLeft", false);
}
if (isOnLadder && rigidbody2D.velocity == new Vector2 (0, 0)) {
animator.SetBool ("IdleRight", false);
animator.SetBool ("IdleLeft", false);
animator.SetBool ("RunRight", false);
animator.SetBool ("RunLeft", false);
animator.SetBool ("ClimbIdle", true);
animator.SetBool ("Climb", false);
animator.SetBool ("ShootRight", false);
animator.SetBool ("ShootLeft", false);
animator.SetBool ("RunShootRight", false);
animator.SetBool ("RunShootLeft", false);
}
if (isOnLadder && rigidbody2D.velocity != new Vector2 (0, 0)) {
animator.SetBool ("IdleRight", false);
animator.SetBool ("IdleLeft", false);
animator.SetBool ("RunRight", false);
animator.SetBool ("RunLeft", false);
animator.SetBool ("ClimbIdle", false);
animator.SetBool ("Climb", true);
animator.SetBool ("ShootRight", false);
animator.SetBool ("ShootLeft", false);
animator.SetBool ("RunShootRight", false);
animator.SetBool ("RunShootLeft", false);
}
if (shooting && hasAimRight && isOnLadder == false) {
// if idle and facing right
if (rigidbody2D.velocity == new Vector2 (0, 0)) {
animator.SetBool ("ShootRight", true);
animator.SetBool ("ShootLeft", false);
animator.SetBool ("RunShootRight", false);
animator.SetBool ("RunShootLeft", false);
animator.SetBool ("IdleRight", false);
animator.SetBool ("IdleLeft", false);
animator.SetBool ("RunRight", false);
animator.SetBool ("RunLeft", false);
animator.SetBool ("ClimbIdle", false);
animator.SetBool ("Climb", false);
}
if (rigidbody2D.velocity.x > 0f) {
animator.SetBool ("ShootRight", false);
animator.SetBool ("ShootLeft", false);
animator.SetBool ("RunShootRight", true);
animator.SetBool ("RunShootLeft", false);
animator.SetBool ("IdleRight", false);
animator.SetBool ("IdleLeft", false);
animator.SetBool ("RunRight", false);
animator.SetBool ("RunLeft", false);
animator.SetBool ("ClimbIdle", false);
animator.SetBool ("Climb", false);
}
}
if (shooting && hasAimLeft && isOnLadder == false) {
// if idle and facing left
if (rigidbody2D.velocity == new Vector2 (0, 0)) {
animator.SetBool ("ShootRight", false);
animator.SetBool ("ShootLeft", true);
animator.SetBool ("RunShootRight", false);
animator.SetBool ("RunShootLeft", false);
animator.SetBool ("IdleRight", false);
animator.SetBool ("IdleLeft", false);
animator.SetBool ("RunRight", false);
animator.SetBool ("RunLeft", false);
animator.SetBool ("ClimbIdle", false);
animator.SetBool ("Climb", false);
}
if (rigidbody2D.velocity.x < 0f) {
animator.SetBool ("ShootRight", false);
animator.SetBool ("ShootLeft", false);
animator.SetBool ("RunShootRight", false);
animator.SetBool ("RunShootLeft", true);
animator.SetBool ("IdleRight", false);
animator.SetBool ("IdleLeft", false);
animator.SetBool ("RunRight", false);
animator.SetBool ("RunLeft", false);
animator.SetBool ("ClimbIdle", false);
animator.SetBool ("Climb", false);
}
}
} // end for if (disableAllMovement)!!!!!!!
if (enemyDies) {
disableAllMovement = true;
rigidbody2D.velocity = new Vector2 (0, gravity.y);
gameObject.tag = "DeadEnemy";
rigidbody2D.simulated = false;
gameObject.collider2D.enabled = false;
}
if (enemyDies && isFacingRight == false) {
animator.SetBool ("DieLeft", true);
animator.SetBool ("DieRight", false);
animator.SetBool ("IdleRight", false);
animator.SetBool ("IdleLeft", false);
animator.SetBool ("RunRight", false);
animator.SetBool ("RunLeft", false);
animator.SetBool ("ClimbIdle", false);
animator.SetBool ("Climb", false);
animator.SetBool ("ShootRight", false);
animator.SetBool ("ShootLeft", false);
animator.SetBool ("RunShootRight", false);
animator.SetBool ("RunShootLeft", false);
}
if (enemyDies && isFacingRight) {
animator.SetBool ("DieLeft", false);
animator.SetBool ("DieRight", true);
animator.SetBool ("IdleRight", false);
animator.SetBool ("IdleLeft", false);
animator.SetBool ("RunRight", false);
animator.SetBool ("RunLeft", false);
animator.SetBool ("ClimbIdle", false);
animator.SetBool ("Climb", false);
animator.SetBool ("ShootRight", false);
animator.SetBool ("ShootLeft", false);
animator.SetBool ("RunShootRight", false);
animator.SetBool ("RunShootLeft", false);
}
}
private GameObject ladder;
private bool waypointCollided = false;
void OnTriggerStay2D (Collider2D other)
{
if (other.transform.tag == "LaddCollider") {
isOnLadder = true;
ladder = other.gameObject;
} else {
isOnLadder = false;
}
if (other.transform.tag == "Waypoint") {
bill = Random.Range (0, 2);
doWaypointOnce = false;
waypointCollided = true;
} else {
waypointCollided = false;
}
}
void OnTriggerExit2D (Collider2D other)
{
if (other.transform.tag == "LaddCollider") {
isOnLadder = false;
}
if (other.transform.tag == "Waypoint") {
waypointCollided = false;
}
}
// DAMAGE CONTROL SECTION
public float fallingDeathVelocity = -30;
public int enemyHealth = 3; // 10 bars //
public int enemyMaxHealth = 3;
private bool dieFalling = false;
// for bullets hitting enemy
public int damage0 = 1, damage1 = 3, damage2 = 4, damage3 = 5;
public GameObject explosion0, explosion1, grenExplosion;
void OnCollisionEnter2D (Collision2D other)
{
if (other.gameObject.tag == "PLATFORM" && dieFalling) {
enemyDies = true;
}
/*
// hope this helps to keep enemies away from each other
if (other.transform.tag == "Enemy" || other.transform.tag == "Player") {
if (isOnLadder) {
startWaitTimer = false;
waitCounterMax = Random.Range (waitMin, waitMax);
waitCounter = 0;
LadderDecider ();
} else if (climbUp) {
startWaitTimer = true;
rigidbody2D.velocity = new Vector2 (0, 1f * climbLadderSpeed * Time.deltaTime);
walkRight = false;
climbUp = true;
} else if (climbDown) {
startWaitTimer = true;
rigidbody2D.velocity = new Vector2 (0, -1f * climbLadderSpeed * Time.deltaTime);
walkRight = false;
climbDown = true;
} else if (isOnLadder == false) {
startWaitTimer = false; // stop timer
decided = false; // reset
walkLeft = false; // reset
walkRight = false; // reset
waitCounterMax = Random.Range (waitMin, waitMax);
waitCounter = 0;
WalkIdleDecider ();
}
}
*/
}
// Update is called once per frame
void FixedUpdate ()
{
// makes sure the players health cannot go over its maximum value.
if (enemyHealth > enemyMaxHealth) {
enemyHealth = enemyMaxHealth;
}
if (enemyHealth <= 0) {
enemyDies = true;
// Destroy (gameObject); // THIS IS TEMPORARY
}
if (rigidbody2D.velocity.y < fallingDeathVelocity) {
dieFalling = true;
enemyHealth = 0;
} else {
dieFalling = false;
}
}
private bool gotShot = false;
void OnTriggerEnter2D (Collider2D other)
{
if (other.transform.tag == "LaddCollider") {
transform.position = new Vector3 (other.transform.position.x, transform.position.y, 0);
}
if (other) {
if (other.transform.tag == "Bullet_0" && gameObject.transform.tag == "Enemy") {
if (other.transform.name == "Bullet_0_Left" || other.transform.name == "Bullet_0_Right" || other.transform.name == "Bullet_0_Left(Clone)" || other.transform.name == "Bullet_0_Right(Clone)") {
gotShot = true;
enemyHealth -= damage0;
Instantiate (explosion0, other.transform.position, Quaternion.identity);
Destroy (other.gameObject);
}
if (other.transform.name == "Bullet_1_Left" || other.transform.name == "Bullet_1_Right" || other.transform.name == "Bullet_1_Left(Clone)" || other.transform.name == "Bullet_1_Right(Clone)") {
gotShot = true;
enemyHealth -= damage1;
Instantiate (explosion0, other.transform.position, Quaternion.identity);
Destroy (other.gameObject);
}
if (other.transform.name == "GrenadeLauncher_0_Left" || other.transform.name == "GrenadeLauncher_0_Right" || other.transform.name == "GrenadeLauncher_0_Left(Clone)" || other.transform.name == "GrenadeLauncher_0_Right(Clone)") {
gotShot = true;
enemyHealth -= damage2;
Instantiate (grenExplosion, other.transform.position, Quaternion.identity);
Destroy (other.gameObject);
}
if (other.transform.name == "Rocket_0_Left" || other.transform.name == "Rocket" || other.transform.name == "Rocket_0_Left(Clone)" || other.transform.name == "Rocket_0_Right(Clone)") {
gotShot = true;
enemyHealth -= damage3;
Instantiate (explosion1, other.transform.position, Quaternion.identity);
Destroy (other.gameObject);
}
}
} else {
gotShot = false;
}
if (other.transform.tag == "Waypoint") {
//bill = Random.Range (0, 2);
doWaypointOnce = false;
waypointCollided = true;
} else {
waypointCollided = false;
}
}
}
That's the whole script for my enemy's movement. It goes on all enemies in the scene. That's why I have the special damage control section at the bottom, its for receiving collisions from bullets and the such. Instead of having a seperate DamageControlScript on the enemies.
I hope someone can help. Sorry bout the long script. Its taken me about 4 days of coding to write and rewrite it, trying to get it right. Lots is commented out so be aware of that.
$$anonymous$$oderator here with a comment and some posting advice. I read through your question text, and your AI movement seems both complex and quite far ahead already. If you've got this kind of AI behaviour done from just 8 months of coding experience, you've reason to be proud. :) Well done!
As for the posting advice, I recommend you try and boil down the code you post to only the part of the script that has to do with the ladder interaction. This is a huge chunk of code to read, it takes me a while just scrolling past it. I think you'll reach a much larger audience if you can remove the parts that work and you don't need help with, allowing people to focus on the broken ladder code. :)
LOL Yeah I kinda didn't think it would be a good idea to ask the question like that. Well If that's all ai behavour basically is then that wasn't that hard. Just took a lot of working out and trial and error, doing things within unitys capabilities. Its 1st time I've posted. Ive been reading the scripts here to better my coding so I thought I owed it to the unity answers to display my ai script as a thank you for letting me learn so much from unity answers and the unity scripting ref.
I work round the clock so I've gotten good - fast I think. . At least I'm doing better than when I started. I couldn't even script over 10 months ago, I was trying to use playmaker but got frustrated too much about all its limitations, so I took a big swollow and dived into c# program$$anonymous$$g in unity. I read a few books specifically aimed at unity and did three of four tutorials, but mostly I've learnt from making my own games, trial and error. I can make lots of different types of games now and have over 42 concept projects that basically lead up to this one I'm on now.
I've been focusing on generating the levels in nearly all of those 42 projects so I'm getting pretty good at generating platformer games. Can do almost anything now from a cloudberry kingdom style to others in my concepts folder that have never been done before... at least I think.
But ok I'll focus on the ladder code. Thanks.
Answer by Kastenessen · Jan 23, 2015 at 11:29 PM
Ive since worked it out, I needed to add more control bools and I also had some bools in the wrong place. Its working way better now, but I won't post the code, its over 2500 lines now cause It does new things now like hunts the player down and runs away.
I'll have to work out how to do the code indentation properly if I'm going to keep asking questions lol. Thanks peeps!
OP, would you $$anonymous$$d sending me the 2500 lines code via email? Im having a bad time tryng to setup my enemy AI on a 2d plataformer game, and i cant find any good material to study on this, i really like the raycasts idea but its not working 100% on what i want, i would really appreciate if i could read your new code. $$anonymous$$y email is danielbezerrakmx@gmail.com, thanks in advance!
Email sent. I seemed to have more problems when I tried using colliders for checks other than raycasts. So until I learn another way, I'll use raycasts.
Your answer
Follow this Question
Related Questions
How to make my character stop stuttering when walking down a slope? 2 Answers
Rigidbody Platform Character Movement 0 Answers
Another Double Jump Question 0 Answers
Non-symmetrical Character walk left animation. 0 Answers
Simple AI In 2D - C# 1 Answer