Hey there!
I’ve just managed to make my first function of a Finite State Machine that will control a bot ship (that can be allied or enemy). However, I’ve noticed the the Main Thread times when from ~13ms to ~45ms once I implemented it. Once I made that single ship into four diferent ships, the time went up to ~80ms.
However, the game is supposed to be able to have dozens or more ships in visual range. So using the “disable AI script when out of range” trick wont help that much.
So, do you guys have any tip that might help me reduce the AI weight?
Thanks in advance.
JPB18
EDIT: Someone asked me for the code, here it is
:
ShipAI.js:
#pragma strict
//lets start by creating some enumerations
enum Formation {close, standard, loose}
enum ShipType {Frigate, AttackShip, Cruiser, BattleShip}
//now le variables
var type : ShipType;
var formation : Formation = Formation.standard;
var leader : GameObject;
var defence : boolean;
var merchant : boolean;
var minDistance : float;
var followDistance : float;
var interceptRange : float;
var dockStation : float;
var dockShip : float;
var defenseStation : float;
var defenseShip : float;
var arriveTime : float;
var presenceTime : float = 180.0f; //3 minutes
//other scripts
var target : shipTarget;
var triggers : shipTriggers;
var props : shipProperties;
var move : shipMovement;
//other variables
var faceAngle : float = 1.0f;
function Start () {
triggers = gameObject.GetComponent(shipTriggers);
target = gameObject.GetComponent(shipTarget);
props = gameObject.GetComponent(shipProperties);
move = gameObject.GetComponent(shipMovement);
arriveTime = Time.time;
}
function Update () {
if(!props.playerProps.isPlayer)
{
if(hasLeader()) {
if(getFormation() == formation.close) {
follow(leader);
}
}
}
}
//this function checks if there's a leader
function hasLeader() : boolean {
return leader != null;
}
//checks if the ship is in follow distance from game object
//pre target == leader, target != null
//pre target.transform.tag == "Ship"
function isFollowDistance(target : GameObject) : boolean {
var distance : float = Vector3.Distance(target.transform.position, transform.position);
return distance <= followDistance;
}
//checks if the ship is too close to another one
//pre target != null
//pre target.transform.tag == "Ship"
function isTooClose(target : GameObject) : boolean {
var distance : float = Vector3.Distance(target.transform.position, transform.position);
return distance <= minDistance;
}
function getFormation() : Formation {
return formation;
}
//this functions gets the forward speed of a target ship
//pre target.transform.tag == "Ship"
function getSpeed(target : GameObject) : float{
return target.rigidbody.velocity.z;
}
//this function checks if our ship is slower than the target ship
//pre target.transform.tag == "Ship"
function isSlower(target : GameObject) : boolean {
return getSpeed(target) > getSpeed(gameObject);
}
//this function checks if our ship is faster than the target ship
//pre target.transform.tag == "Ship"
function isFaster(target : GameObject) : boolean {
return getSpeed(target) < getSpeed(gameObject);
}
//this function attempts to match the ship speed with its target
//pre target.transform.tag == "Ship"
function matchSpeed(target : GameObject) {//pre target.transform.tag == "Ship"//pre leader.transform.tag == "Ship"return getSpeed(target) > getSpeed(gameObject);
if(isSlower(target)) {
move.increaseSpeed();
}
else if (isFaster(target)) {
move.decreaseSpeed();
}
}
//this function checks if the ship is looking at target
//pre target.transform.tag == "Ship"
function isLookingAt(target : GameObject) {
var targetDir = target.transform.position - transform.position;
var forward = transform.forward;
var angle = Vector3.Angle(targetDir, forward);
return angle < faceAngle;
}
//this function makes the ship look at target
//pre target.transform.tag == "Ship"
function LookAt(target : GameObject) {
AlignX(target);
AlignY(target);
}
//this function check if a value is negatve
function isNeg(dir : float) : boolean {
return dir < 0;
}
//this function checks if a value is positive
function isPos(dir : float) : boolean {
return dir > 0;
}
//this function aligns the ship to the target ship on X
//pre target.transform.tag == "Ship"
function AlignX(target : GameObject) {
var v3 : Vector3 = transform.InverseTransformPoint(target.transform.position);
if(isNeg(v3.x)) {
move.turnLeft();
}
else if(isPos(v3.x)) {
move.turnRight();
}
}
//this function aligns the ship to the target ship on Y
//pre target.transform.tag == "Ship"
function AlignY(target : GameObject) {
var v3 : Vector3 = transform.InverseTransformPoint(target.transform.position);
if(isNeg(v3.y)) {
move.turnDown();
}
else if(isPos(v3.y)) {
move.turnUp();
}
}
//this function aligns the ship to the target ship on Z
//pre target.transform.tag == "Ship"
function AlignZ(target : GameObject) {
if(target.transform.rotation.z > transform.rotation.z) {
move.rotLeft();
}
else if (target.transform.rotation.z > transform.rotation.z) {
move.rotRight();
}
}
//this function makes the ship follow target
//pre target.transform.tag == "Ship"
function follow(target : GameObject) {
if(!isLookingAt(target)) {
LookAt(target);
}
if(isTooClose(target)) {
if(!move.isAtMin()) {
move.decreaseSpeed();
}
}
else if(!isFollowDistance(target)) {
if(!move.isAtMax()) {
move.increaseSpeed();
}
}
else {
move.matchSpeed(target);
}
}
If you guys need to see any other function, let me know…
It may be that your code is just reaaaalllyyy inefficient so maybe post that for others to go through? I've done AIs before and they are a nightmare :P
– JamsterAt a guess, I'd say it's due to the function on line 56. But I might be wrong - I might be able to give you a more precise answer if you actually showed us the script in question.... ;)
– tanoshimiJust edited the post with the script with the code in question. If you want to see any of the methods I don't show in there, just ask...
– JPB18