change object state using enum switch from another script
I've searched extensively and either I'm not seeing/getting it, or the question isn't answered.
I have simple Script to control the player, and use an enum to control the characters state:
public void SetState(pState p) {
playerState = p;
r = GetComponent<Rigidbody>();
switch (playerState) {
case pState.ascend:
Debug.Log("Flap");
r.AddForce(Vector3.up * 10, ForceMode.Impulse);
playerState = pState.descend;
break;
case pState.descend:
Debug.Log("falling");
break;
case pState.dead:
Debug.Log("dead");
break;
}
}
Another script handles the input and when space is pressed should change the players state, like so:
using UnityEngine;
using System.Collections;
public class UserInput : MonoBehaviour {
public GameObject p;
public PlayerScript ps;
void Start () {
ps = p.GetComponent<PlayerScript>();
}
void Update () {
if (Input.GetKeyDown(KeyCode.Space)) {
ps.playerState = pState.ascend;
}
}
}
Please can someone explain what I'm doing wrong/why this doesn't work? Bonus points if you can guess what game I'm emulating.
Thanks
Dan
You are setting the pState.ascend in your UserInput class, but why are you just not using the public method of SetState() in the PlayerControl class? Without running through the switch logic you are not seeing the force being added, which probably makes you think the state is not being switched. Once you get the component and space is pressed in the UserInput class, call ps.SetState(pState.ascend).
The SetState() then handles the updating of the state for you, as well as the state specific settings.
Also....Flappy Bird....
Thanks Hanoble.
I tried that initially and it still doens't work.
public void SetState(pState p) {
playerState = p;
r = GetComponent<Rigidbody>();
switch (playerState) {
case pState.ascend:
Debug.Log("Flap");
r.AddForce(Vector3.up * 10, Force$$anonymous$$ode.Impulse);
playerState = pState.descend;
break;
case pState.descend:
Debug.Log("falling");
break;
case pState.dead:
Debug.Log("dead");
break;
}
}
and then in UserInput:
if (Input.Get$$anonymous$$eyDown($$anonymous$$eyCode.Space)) {
ps.SetState(pState.ascend);
}
This does print "flap" but why doesn't it addForce to the player?
Oh, and you're right. 10 extra points for you!
If it does print "flap", then you are getting into that section of code. The next step is to debug the rigidbody and make sure the force is being added. The RB is not set to kinematic correct? There is a RB on there as well correct? Both simple things, but we have all overlooked these simple things in the past and spent waaayyyy too much time troubleshooting obvious fixes.
Run back through the setup of the RB and make sure everything is correct. If it is still not working, attach visual studio to the Unity instance and place a breakpoint at the AddForce line and try to further breakdown what is going on.
The rigidbody is set up correctly. If I set the pState to ascend in the inspector at run time he recieves the impulse with no problem. If I set playerState = pState.ascend; in the Start() of the PlayerScript, it works fine. It's only when being set from another script. I'm not sure how to use a breakpoint but did take a look at them. $$anonymous$$y scripts now look like this:
PlayerScript
using UnityEngine;
using System.Collections;
public enum pState { ascend, descend, dead };
public class PlayerScript : $$anonymous$$onoBehaviour {
public pState playerState;
public Rigidbody r;
void Start () {
// playerState = pState.descend;
playerState = pState.ascend;
}
void FixedUpdate () {
SetState(playerState);
Debug.Log("state is: " + playerState);
}
public pState SetState(pState p) {
playerState = p;
r = GetComponent<Rigidbody>();
switch (playerState) {
case pState.ascend:
Debug.Log("Flap");
r.AddForce(Vector3.up * 10, Force$$anonymous$$ode.Impulse);
playerState = pState.descend;
break;
case pState.descend:
Debug.Log("falling");
break;
case pState.dead:
Debug.Log("dead");
break;
}
return playerState;
}
}
UserInput
using UnityEngine;
using System.Collections;
public class UserInput : $$anonymous$$onoBehaviour {
public GameObject p;
public PlayerScript ps;
void Start () {
ps = p.GetComponent<PlayerScript>();
}
void Update () {
if (Input.Get$$anonymous$$eyDown($$anonymous$$eyCode.Space)) {
ps.SetState(pState.ascend);
}
}
}
It doesn't make a difference whether I return the playerState in setState or just have it return void.
Thanks again.
Dan
Can you tell me why you call SetState() in FixedUpdate() ?
Only reason it's called in FixedUpdate() is because I'm using addForce(). Force of habit to use FixedUpdate when changing velocity etc. Calling in Update() yields the same issue. Thanks.
I just plugged in your scripts to a project and it does work. I created a new scene, put both scripts on a cube, drug in the cube and scripts to the inspector as needed, hit play and hit space bar to get my cube co$$anonymous$$g back up. As the cube gains more momentum going down it takes more button presses to bring it back up, and the space presses continue to add force, so if I simply mash space over and over I can get the cube to continue to climb for several seconds after I stop pressing space. That is probably not the exact mechanic you are looking for, but that is more tweaks than it is fixing why it does not work.
I am not sure as to exactly what is not working on your end, but the scripts do work. I would also suggest removing the SetState() in the FixedUpdate(), as there is no reason to set the state every frame.
Answer by dead_byte_dawn · Jun 09, 2017 at 12:40 AM
Robert Miles has a pretty good chapter on Objects, Structures and References. I'd start here: http://www.csharpcourse.com/