I was hoping you could proof read my script, because for some reason, the variable “ready” doesn’t change the outcome of the code… What I mean is, you can fire directly after you reload, bypassing the timer… There should be a time of about three seconds when you can’t fire (Because you would be reloading) but thats not the case. I was hoping somebody could see something I did wrong… Thanks guys!
P.s. The script has no errors, and works fine, accept for this one problem…
//Clip Variables
var fullClip : int = 30;
var currentClip : int = 30;
var clipEmpty : boolean;
//Time Variables
var fireTime : float = 0.1;
var reloadTime : float = 3;
//GUI Variable
var guiObject : GUIText;
//Reload Variable
var ready : boolean;
//Start function
function Start () {
if (!ready)
return;
while (true) {
guiObject.guiText.text = "Ammo Remaining In Clip: " + currentClip;
while (!Input.GetMouseButton(0)) {
yield;
}
Fire ();
yield WaitForSeconds (fireTime);
}
}
while (true) {
while (!Input.GetMouseButton(1)) {
yield;
}
Reload ();
yield WaitForSeconds(reloadTime);
}
//Fire Function
function Fire () {
Debug.Log("Left Mouse Button Pressed");
ready = true;
clipEmpty = false;
currentClip -=1;
if (currentClip <1)
{
guiObject.guiText.text = "Reload";
currentClip = 0;
clipEmpty = true;
ready = false;
}
}
//Reload Function
function Reload () {
Debug.Log("Right Mouse Button Pressed");
clipEmpty = false;
ready = false;
currentClip = fullClip;
guiObject.guiText.text = "Reloading...";
yield WaitForSeconds(reloadTime);
ready = true;
guiObject.guiText.text = "Ammo Remaining In Clip: " + currentClip;
}
This is an approach to the problem I wouldn’t have thought of. For something like firing a gun, I would have placed the game logic in the Update() function so that it can run every frame instead of using while loops. I’m sorry I can’t deduce from looking at it how it works exactly because it is such an unorthodox approach, but I can show you how I would do it.
//Clip Variables
var fullClip : int = 30;
var currentClip : int = 30;
//Time Variables
var fireTime : float = 0.1;
var reloadTime : float = 3;
//GUI Variable
var guiObject : GUIText;
enum GunState {ReadyToFire, Cooldown, Reloading};
var currentState = GunState.ReadyToFire;
function Start(){
guiObject.guiText.text = "Ammo Remaining In Clip: " + currentClip;
}
//Update function
function Update () {
if(Input.GetMouseButton(0)){
Fire();
}
if(Input.GetMouseButton(1)) {
Reload();
}
}
//Fire Function
function Fire () {
if(currentState == GunState.ReadyToFire){
Debug.Log("Left Mouse Button Pressed");
currentClip -=1;
if (currentClip == 0) {
Reload();
} else {
currentState = GunState.Cooldown;
WaitForCooldown();
}
}
}
//Reload Function
function Reload () {
if(currentState == GunState.ReadyToFire){
Debug.Log("Right Mouse Button Pressed");
currentState = GunState.Reloading;
guiObject.guiText.text = "Reloading...";
WaitForReload();
}
}
function WaitForCooldown() {
yield WaitForSeconds(fireTime);
currentState = GunState.ReadyToFire;
guiObject.guiText.text = "Ammo Remaining In Clip: " + currentClip;
}
function WaitForReload() {
yield WaitForSeconds(reloadTime);
currentClip = fullClip;
currentState = GunState.ReadyToFire;
guiObject.guiText.text = "Ammo Remaining In Clip: " + currentClip;
}
Sorry, it’s not commented (except for the ones you wrote) but if you have any questions, I’d be happy to answer them.
you declare “ready” to be false and then you tell the Start function to return if ready is not not false (true) so Start() which only fires off once just returns and your scripting is never accessed again.
Wow, thanks, that works perfectly! Do you mind if I use your code? Also, can you explain what this does: (Like what “enum” does) enum GunState {ReadyToFire, Cooldown, Reloading};
I don’t mind you using the code at all, I posted it here for a reason =P.
Enum (enumeration) basically makes a new customized “type” of variable. For example, a boolean is a type. An int is a type. Now, GunState is a type.
var ready : boolean; //ready can be either true or false
var myInt : int; //can be any integer from -65536 to 65535
var currentState : GunState; //can only be ReadyToFire, Cooldown, or Reloading
Since the gun is essentially a finite state machine (it can only be in one of three different states), declaring your own enum type for it allows any state that the gun is in to be easily identified just by looking at the code. In your version, your were doing the same thing, but using booleans. Since booleans have only 2 possible values (true or false), you cannot represent three states. So instead you used two booleans (ready and clipEmpty).
However, to change the state, you might have to change two variables.
State A = ReadyToFire = ready and !clipEmpty
State B = Cooldown = !ready and !clipEmpty
State C = Reloading = !ready and clipEmpty
State D = ??? = ready and clipEmpty ← degenerate state!!! ← bad!!!
State D is impossible in real life. A gun cannot be ready to fire with an empty clip. This is why GunState has no possible value for this situation. You can still show represent this state with two booleans (which is bad).
So, in short, I used an enum type to represent states in the gun because to change the state I only have to manipulate one variable, and it increases the readability and reliability of the code. Enums were invented so they could be used like this, and I think scripters should start using them more often for state machines. They are a very powerful tool.
Thanks! Oh, can I sak you one more question? If I want to call a function, can it be on a different script? Like, for instance, It fires a ray, and if something intersects it, it tells that object “Damage”, or something like that, would I use the same “Damage ();” thing?