For my first practice project, I’m doing RTS/Defense style game.
But before I get any further along, I want to know if I’m going about coding the units in the best manner.
What I have is working so far, but I’m new to Unity, and I’d like some advice on if I’m going about this in a way that won’t cause problems later, or if I’m making things harder than they need to be, etc.
I’m not looking for code optimization at the moment, per se. (though such suggestions are welcome) But rather, if my overall approach is appropriate so far.
Anyway, here’s a brief set up:
I have some vehicles. The vehicles have turrets.
For testing purposes, I can click on a unit to select it. While selected, I can click on another unit and that will set the target for the currently selected unit. It will then chase the unit down while keeping it’s turret aimed at the target.
Relevant components:
The units are rigidbodies so they can crash and stuff.
They have a projector to indicate if they are selected.
Script: Unit_Interaction script (so they player can select and target by clicking)
Script: Unit_Controler (Controls the vehicle movement, and keeps track of waypoints, targets, and general AI)
Script: Turret_Controler (Controls the turret(s) with target objects passed from the Unit_Controler script)
I’ve tried to comment the code as best I can.
Unit_Controler:
#pragma strict
var turnrate : float; //vehicle turn rate
var accell : float; //vehicle accelleration
var topspeed : float;
var target : GameObject; //current target
var turrettarget : GameObject; //current turret target
var curWPT : Vector3; //current waypoint location (not used yet)
private var rotation : Quaternion;
private var speed : float; //current speed
private var curtopspeed : float; //current top speed (changes based on distance to target for smarter accelleration)
var hasWPT : boolean; //do I have any destination at all?
hasWPT = true;
accell *= .1; //accell is multiplied by .1 for actual value. The larger number are easier to handle when designing the vehicles
var destination : Vector3; //current destination, might be a waypoint, might be a target location
function Update () {
if(hasWPT == true) { //early out if no destination
destination = target.transform.position; //destination is currently hardcoded as the current target
//set speed
var distance = Vector3.Distance(destination, transform.position); //find distance to destination location
if(distance > 10) { //is destination further than 10 meters away?
speed += accell; //increase speed by accelleration
//smart topspeed
if(distance <= topspeed) { //is the destination distance less than top speed as measured in distance?
curtopspeed = topspeed * distance/topspeed; //current tops speed will be less than normal topspeed. The closer the destination the lower current top speed will be
} else { //destination is suffiently far enough away to move at max speed
curtopspeed = topspeed; //set current top speed to top speed (max)
}
//
if(speed > curtopspeed) {speed = curtopspeed;} //make sure current speed isn't above current top speed. Set to current top speed if neccessary
if(speed < (curtopspeed*-1) / 2) {speed = (curtopspeed*-1) / 2;} //if moving in reverse, current top speed is half normal (reverse not supported yet)
} else { //destination is within 10 meters
//slow down and stop
speed -= accell * 2; //reduce speed (decelleration is double the accelleration rate)
if(speed < 0) {speed = 0;} //if speed reduces past 0, set to 0. (moving in reverse not supported yet)
}
//turn
rotation = Quaternion.LookRotation(destination - transform.position); //turning required to face destination
transform.rotation = Quaternion.RotateTowards(transform.rotation, rotation, turnrate * Time.deltaTime); //do vehicle rotation
transform.localEulerAngles.x = 0; //keep vehicle level
transform.localEulerAngles.z = 0;
transform.Translate(0, 0, speed * Time.deltaTime); //do new vehicle location
//I have to add some code that detects if a unit's wheeles are touching the ground.
//If they aren't, then make it so it can't change it's own rotation and position - let physics do it.
}
}
Turret_Controler:
#pragma strict
var aimspeed : float; //turret rotation speed
var ylimit : float; //turret rotation limit from straight ahead
var xlimit : float; //turret elevation limit
var turret : GameObject; //object that rotates
var gun : GameObject; //object that elevates
private var rotation : Quaternion;
private var elevation : Quaternion;
function Update () {
var mytarget = GetComponent(Unit_Controler).turrettarget;
if(mytarget != null) { //rotation required to face target
rotation = Quaternion.LookRotation(mytarget.transform.position - turret.transform.position);
elevation = Quaternion.LookRotation(mytarget.transform.position - gun.transform.position);
} else { //rotation required to return to forward facing
rotation = Quaternion.LookRotation(transform.position - turret.transform.position);
elevation = Quaternion.identity;
}
//rotate the turret
turret.transform.rotation = Quaternion.RotateTowards(turret.transform.rotation, rotation, aimspeed * Time.deltaTime);
turret.transform.localEulerAngles.x = 0; //keep other turret axes level
turret.transform.localEulerAngles.z = 0;
//elevate the gun
gun.transform.rotation = Quaternion.RotateTowards(gun.transform.rotation, elevation, aimspeed * Time.deltaTime);
gun.transform.localEulerAngles.y = 0; //keep other gun axes level
gun.transform.localEulerAngles.z = 0;
if(ylimit != 0) { //0 = no rotation constraint limit
if(turret.transform.localEulerAngles.y > ylimit turret.transform.localEulerAngles.y <= 180) { //check if rotation is above limit and targert is on that side of me
turret.transform.localEulerAngles.y = ylimit; //set to limit
} else if(turret.transform.localEulerAngles.y < 360-ylimit turret.transform.localEulerAngles.y > 180) { //check if below, etc.
turret.transform.localEulerAngles.y = 360-ylimit; //set to limit
}
}
//hardcode depression limit at 4 deg down, for now
//positive numbers are down, negative numbers are up
if(gun.transform.localEulerAngles.x > 4 gun.transform.localEulerAngles.x <= 180) { //check if elevation is past limit, etc
gun.transform.localEulerAngles.x = 4; //set to limit
}
if(xlimit != 0) { //0 = no limit
if(gun.transform.localEulerAngles.x < 360-xlimit gun.transform.localEulerAngles.x > 180) { //check elevation limit, etc
gun.transform.localEulerAngles.x = 360-xlimit; //set to limit
}
}
}