- Home /
Why is my AI not thinking the collisions fast enough?
Hi guys,
I'm currently working on a project of mine and I've seem to be having a dilemma.
Briefing of the project: it has 1 AI character (currently a sphere) and 4 walls.
What I am trying to achieve: for starters it would be nice if my AI wouldn't go through the wall.
How does it move: My AI script makes it select a number from a random range, and depending on the number chosen it will change its direction in 2D, vertical, horizontal and diagonal.
What works: At the beginning I've only had 4 box colliders arranged perfectly so that it wouldn't get out but it still got out due to the code sending it in an impossible area. I've managed to correct this by applying 4 invisible colliders on each of the walls - total of 16 colliders and each will limit the movement to the specific areas.
What doesn't work: I am now trying to instantiate other walls to close in on the AI to test it, and it seems that at several points it still goes through the walls.
Question: How do I make it stop passing through the walls? Should I limit the x and y position of the AI or is there a simpler way?
If sample code is needed please ask!
Kind regards - Eugen
Edit: Note that the move_dir variable is a float.
function Start () {
move_dir = Random.Range(-2,6);
}
function Update () {
Actions();
}
function Actions () {
if(move_dir == -2){
cow.transform.position.x = cow.transform.position.x - 0.05;
Debug.Log("Este -2");
}
if(move_dir == -1){
cow.transform.position.x = cow.transform.position.x + 0.05;
Debug.Log("Este -1");
}
if(move_dir == 0){
cow.transform.position.y = cow.transform.position.y - 0.05;
Debug.Log("Este 0");
}
if(move_dir == 1){
cow.transform.position.y = cow.transform.position.y + 0.05;
Debug.Log("Este 1");
}
if(move_dir == 2){
cow.transform.position.x = cow.transform.position.x - 0.05;
cow.transform.position.y = cow.transform.position.y - 0.05;
Debug.Log("Este 2");
}
if(move_dir == 3){
cow.transform.position.x = cow.transform.position.x + 0.05;
cow.transform.position.y = cow.transform.position.y + 0.05;
Debug.Log("Este 3");
}
if(move_dir == 4){
cow.transform.position.x = cow.transform.position.x + 0.05;
cow.transform.position.y = cow.transform.position.y - 0.05;
Debug.Log("Este 4");
}
if(move_dir == 5){
cow.transform.position.x = cow.transform.position.x - 0.05;
cow.transform.position.y = cow.transform.position.y + 0.05;
Debug.Log("Este 3");
}
}
function OnTriggerEnter (hit : Collider) {
//Collision with Right Wall
if(hit.gameObject.tag == "Right Wall 1"){
move_dir = RW_random[Random.Range(0, (RW_random.length))];
Debug.Log("It's turned to" + move_dir);
}
if(hit.gameObject.tag == "Right Wall 2" || hit.gameObject.tag == "Right Wall 3"){
move_dir = RW_random1[Random.Range(0, (RW_random1.length))];
Debug.Log("It's turned to" + move_dir);
}
if(hit.gameObject.tag == "Right Wall 4"){
move_dir = RW_random2[Random.Range(0, (RW_random2.length))];
Debug.Log("It's turned to" + move_dir);
}
//Collision with Left Wall
if(hit.gameObject.tag == "Left Wall 1"){
move_dir = LW_random[Random.Range(0, (LW_random.length))];
Debug.Log("It's turned to" + move_dir);
}
if(hit.gameObject.tag == "Left Wall 2" || hit.gameObject.tag == "Left Wall 3"){
move_dir = LW_random1[Random.Range(0, (LW_random1.length))];
Debug.Log("It's turned to" + move_dir);
}
if(hit.gameObject.tag == "Left Wall 4"){
move_dir = LW_random2[Random.Range(0, (LW_random2.length))];
Debug.Log("It's turned to" + move_dir);
}
//Collision with Top Wall
if(hit.gameObject.tag == "Top Wall 1"){
move_dir = TW_random[Random.Range(0, (TW_random.length))];
Debug.Log("It's turned to" + move_dir);
}
if(hit.gameObject.tag == "Top Wall 2" || hit.gameObject.tag == "Top Wall 3"){
move_dir = TW_random1[Random.Range(0, (TW_random1.length))];
Debug.Log("It's turned to" + move_dir);
}
if(hit.gameObject.tag == "Top Wall 4"){
move_dir = TW_random2[Random.Range(0, (TW_random2.length))];
Debug.Log("It's turned to" + move_dir);
}
//Collision with Bottom Wall
if(hit.gameObject.tag == "Bot Wall 1"){
move_dir = BW_random[Random.Range(0, (BW_random.length))];
Debug.Log("It's turned to" + move_dir);
}
if(hit.gameObject.tag == "Bot Wall 2" || hit.gameObject.tag == "Bot Wall 3"){
move_dir = BW_random1[Random.Range(0, (BW_random1.length))];
Debug.Log("It's turned to" + move_dir);
}
if(hit.gameObject.tag == "Bot Wall 4"){
move_dir = BW_random2[Random.Range(0, (BW_random2.length))];
Debug.Log("It's turned to" + move_dir);
}
}
Code might be helpful - how are you moving this thing? CharacterController, position update, physics?
Do the walls have rigidbodies? or are you just trying to have the AI remain in a certain area and still allow like say a player to enter that area?
it could be that you are randomly co$$anonymous$$g up with directions that take you further and further through the collider.
You may want to have the AI move in relation to it's starting position ins$$anonymous$$d of when it hits a boundary. once the AI traveled to the threshold you could have the AI stop moving while you keep randomly generating new direction and check to make sure they don't move you further away.
You may also want to just set up multiple paths that it can follow broken into segments. Then randomly pick from several predeter$$anonymous$$ed paths at the end of each segment. This would take a little work up front but could guarantee that your AI remained in a certain area.
One other thing; You may just want to setup some code that checks if you are a certain distance away from the starting position, which would be beyond your colliders, and if so have the AI move back to the starting position then go back into the random move sequence.
Hope one of these ideas helps.
I also believe this is your problem.
You could setup multiple invisible game objects along the boundary area you want the AI to stay inside of. When you hit a collider then randomly select a transform from one of the objects and move towards it with it's value being the maximum movement distance you could never move beyond those objects.
Another Option: Ins$$anonymous$$d of having the colliders limit the area the AI can move in use a radius based on the starting location.
This way it doesn't matter if your AI goes a little further than the boundry as it will always try a new direction if it is to far from it's starting location.
Please don't make it float, keep it int. Floating point comparison is a nightmare (from past experience). You assign the variable 2, it reads it as 1.999999 or 2.000001. You'll never be able to satisfy your if() condition.
Is your sphere a rigidbody? if yes, is it kinematic or gravity based? Are the random move directions in the OnTriggerEnter follow the same range as in Start() method?
Also, use hit.gameObject.comparetag("Right Wall 1"), its better than comparing two string references using '=='.
Answer by 3dGeek · Apr 23, 2013 at 09:44 PM
I've seen this issue before. physics doesn't always work if you move objects with colliders from the Update() method. You need to use FixedUpdate().
hope this helps,
Mike
Yup, that fixed my problem.
All of you please move some of your comments as answers so I can choose them as correct as well as most are going to help me in further developing this app :)
Your answer
Follow this Question
Related Questions
Collider Vision AI question. Solved! 0 Answers
Character Collider doesn't collide with other Colliders 2 Answers
Detecting collisions with raycast or not? 1 Answer
Simple AI and Animation 2 Answers
Stop Dashing through walls 1 Answer