- Home /
Enemy AI script trouble(Js to c#)
So I made this c# code from JS from the old fps tutorial. There r no errors but still my AI script seems not to be working(robot doesn't move or anything). Didn't find anything similar on the internet and now I have to ask for some help because I've spent tons of time trying to figure out what's wrong.
I know there is too much code but I don't know which part doesn't work:
using UnityEngine;
using System.Collections;
[RequireComponent(typeof(CharacterController))]// Make sure there is always a character controller
public class AI : MonoBehaviour
{
public float speed = 3.0f;
public float rotationSpeed = 5.0f;
public float shootRange = 15.0f;
public float attackRange = 30.0f;
public float shootAngle = 4.0f;
public float dontComeCloserRange = 5.0f;
public float delayShootTime = 0.35f;
public float pickNextWaypointDistance = 2.0f;
public Transform target;
private float lastShot = -10.0f;
void Start()
{
// Auto setup player as target through tags
if (target == null && GameObject.FindWithTag("Player"))
target = GameObject.FindWithTag("Player").transform;
Patrol();
}
IEnumerator Patrol()
{
AutoWaypoint curWayPoint = AutoWaypoint.FindClosest(transform.position);
while (true)
{
Vector3 waypointPosition = curWayPoint.transform.position;
//If we're close to a waypoint, we'll go ahead and pick the next one.
if (Vector3.Distance(waypointPosition, transform.position) < pickNextWaypointDistance)
{
curWayPoint = PickNextWaypoint(curWayPoint);
}
//We'll attack the player if he is in sight.
if (CanSeeTarget())
{
yield return StartCoroutine("AttackPlayer");
}
// Move towards our target
MoveTowards(waypointPosition);
}
}
bool CanSeeTarget()
{
//If the target is out of range, we cannot see it.
if (Vector3.Distance(transform.position, target.position) > attackRange)
{
return false;
}
RaycastHit hit;
if (Physics.Linecast(transform.position, target.position, out hit))
{
return hit.transform == target;
}
return false;
}
IEnumerator Shoot()
{
// Start shoot animation
animation.CrossFade("shoot", 0.3f);
// Wait until half the animation has played
yield return new WaitForSeconds(delayShootTime);
// Fire gun
BroadcastMessage("Fire");
// Wait for the rest of the animation to finish
yield return new WaitForSeconds(animation["shoot"].length - delayShootTime);
}
IEnumerator AttackPlayer()
{
//We'll set up the position the player was last visible.
Vector3 lastVisiblePlayerPosition = target.position;
while (true)
{
if (CanSeeTarget())
{
//If our target is dead, we need to quit hunting.
if (target == null)
{
yield return null;
}
//If the target is too far away, we need to give up the hunt.
float distance = Vector3.Distance(transform.position, target.position);
if (distance > shootRange * 3.0f)
{
yield return null;
}
lastVisiblePlayerPosition = target.position;
//If we aren't in the "Don't come closer range" yet, we'll move toward the last known
//position.
if (distance > dontComeCloserRange)
{
MoveTowards(lastVisiblePlayerPosition);
}
else
{
RotateTowards(lastVisiblePlayerPosition);
}
Vector3 forward = transform.TransformDirection(Vector3.forward);
Vector3 targetDirection = lastVisiblePlayerPosition - transform.position;
targetDirection.y = 0;
float angle = Vector3.Angle(targetDirection, forward);
//We'll start shooting at the player if he's in sight and within range.
if (distance < shootRange && angle < shootAngle)
{
yield return StartCoroutine("Shoot");
}
}
else
{
yield return StartCoroutine("SearchPlayer", lastVisiblePlayerPosition);
//If at any point the player leaves visibility, we should stop attacking.
if (!CanSeeTarget())
{
yield return null;
}
}
}
}
IEnumerator SearchPlayer(Vector3 position)
{
// Run towards the player but after 3 seconds timeout and go back to Patroling
float timeout = 3.0f;
while (timeout > 0.0f)
{
MoveTowards(position);
// We found the player
if (CanSeeTarget())
{
yield return null;
}
timeout -= Time.deltaTime;
}
}
IEnumerator RotateTowards(Vector3 position)
{
SendMessage("SetSpeed", 0.0f);
Vector3 direction = position - transform.position;
direction.y = 0;
if (direction.magnitude < 0.1f)
{
yield return null;
}
//Otherwise we have a target that we can see. As such, we'll rotate
//towards our target.
Vector3 targetPoint = target.position;
Quaternion targetRotation = Quaternion.LookRotation(targetPoint - transform.position, Vector3.up);
transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, Time.deltaTime * 2.0f);
}
IEnumerator MoveTowards(Vector3 position)
{
Vector3 direction = position - transform.position;
direction.y = 0;
if (direction.magnitude < 0.5f)
{
SendMessage("SetSpeed", 0.0);
yield return null;
}
//Otherwise we have a target that we can see. As such, we'll rotate
//towards our target.
Vector3 targetPoint = target.position;
Quaternion targetRotation = Quaternion.LookRotation(targetPoint - transform.position, Vector3.up);
transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, Time.deltaTime * 2.0f);
// Modify speed so we slow down when we are not facing the target
Vector3 forward = transform.TransformDirection(Vector3.forward);
float speedModifier = Vector3.Dot(forward, direction.normalized);
speedModifier = Mathf.Clamp01(speedModifier);
// Move the character
direction = forward * speed * speedModifier;
CharacterController controller = GetComponent<CharacterController>();
controller.SimpleMove(direction * speed);
SendMessage("SetSpeed", speed * speedModifier, SendMessageOptions.DontRequireReceiver);
}
AutoWaypoint PickNextWaypoint(AutoWaypoint currentWaypoint)
{
//Let's find the waypoint where our character will have to turn the least.
//This is the direction the character is walking.
Vector3 forward = transform.TransformDirection(Vector3.forward);
//The closer our two vectors are, the larger the dot product shall be.
var best = currentWaypoint;
float bestDot = -10.0f;
foreach (AutoWaypoint cur in currentWaypoint.connected)
{
Vector3 direction = Vector3.Normalize(cur.transform.position - transform.position);
float dot = Vector3.Dot(direction, forward);
if (dot > bestDot && cur != currentWaypoint)
{
bestDot = dot;
best = cur;
}
}
return best;
}
}
Before we can help you, what have you tried? You're right, there is too much code here, especially when you don't know what's wrong.
Put in debug.log statements in every function, see which ones are getting called, which ones aren't. Rebuild the script from the ground up with one piece at a time, ins$$anonymous$$d of converting the whole script at once.
If you write a big script and it doesn't work, you have no idea what's wrong. Ins$$anonymous$$d, write a piece at a time and get it working. Then add the next piece.
The first thing I've checked on the internet is how to call IEnumerators and Coroutines in C#. Thus the most logical thing would be to use debug.log, thx I'll try it.
It looks like you are trying to call patrol() as just a normal function.
In my experience I always have called IEnumerator functions with a StartCoroutine()
I would try changing the Patrol() in your Start() to a StartCoroutine()
yes, that was the problem. I fixed all coroutines except this one(the first one xD ) maybe because I was too tired.
sorry for reup this necro.. but i have the same problem.. ca npelase someone post the entire working script in c# please?
Answer by perchik · Feb 13, 2014 at 03:50 PM
I stand by my previous comment, but I'm pretty sure your problem is that you can't call IEnumerators in C# like you can in JS. Instead you have to use StartCoroutine
Yes indeed he needs StartCoroutine($$anonymous$$oveTowards)
I've fixed all the Coroutines calls but now I have another trouble xD Robot follows me all the time+doesn't patrol(use waypoints). Any suggestions?
Post it as a new question, but explain what the problem is, what you've tried, and how you've tried to fix it. If you don't understand the code, it's not going to be easy for you moving forward.
Answer by El_Guig · Feb 13, 2014 at 04:13 PM
I believe I looked up the same problem this morning myself, having just switched from JS to C#. I found a very well explained answer here, going along with WaitForSeconds which you probably want to look into: http://answers.unity3d.com/questions/350721/c-yield-waitforseconds.html