I want to play 3 animations on a cube, when a condition is checked the first animation should be played, then when the second condition is checked, the second animation, and the same thing for the last one.
So I've created 3 animations and make them as legacy, then I attached animation component to the cube, and add the animations to it. The problem I have with the script below is that the first animation works fine, but the 2 rest didn't. What should I do to fix that?
Animation CubeRot;
bool Rot = false;
// Use this for initialization
void Start () {
CubeRot = gameObject.GetComponent<Animation>();
}
// Update is called once per frame
void Update () {
if (FindObjectOfType<HoseController>().Rotated1 == true)
{
if (!Rot)
{
CubeRot.Play("Rot1");
Rot = true;
}
}
if (FindObjectOfType<HoseController>().Rotated2 == true)
{
if (!Rot)
{
CubeRot.Play("Rot2");
Rot = true;
}
}
}
Is it because you are setting Rot = true; in the first update. Then the second update requires the Rot variable to be false but its still true from the 1st update?
First:
You require Rot to be false in both if.
Second:
If Rotated1 is true the first part will loop (since you are in the Update) and since you do not set it to false in your if it will continue to loop.
You can even avoid to use both Rotated1 and Rot
Also you should try to avoid the legacy animation component. It should be easy to do the same behaviour in the new Animator component
Finally avoid to use FindObjectOfType each time
Related
I have a character game object, with both an animator and a collider.
Whenever the animator is on, the collider cannot be changed during run-time, though it can be changed in scene editing mode, via the inspector.
No matter what animator properties I change via the inspector, nothing happens.
The feature I've tried to fix was invincibility frames - A co-routine, disabling the character's hit-box for several seconds.
I attempted enabling and disabling the collider's isTrigger property, but the problem persisted - The character still gets hurt while the isTrigger is on.
Code:
private IEnumerator ActivateInvincibility()
{
// 3 seconds of invincibility
_hit_zone.enabled = false; // no effect
_hit_zone.isTrigger = true; // no effect either
yield return new WaitForSeconds(3f);
_hit_zone.enabled = true;
_hit_zone.isTrigger = false;;
}
Called normally, like so: StartCoroutine("ActivateInvincibility");.
Edit:
For clarification, what I want to know is the root of the problem I've encountered, because I suspect more problems could occur because of this one root.
I have also edited out the unimportant lines of code.
//Added control flag
private bool isInvincibility = false;
private IEnumerator ActivateInvincibility()
{
isInvincibility = true;
//wait time
isInvincibility = false;
}
void OnCollisionEnter(Collision collision)//or trigger {
if(!isInvincibility && */Your condition tag name etc/*){
//Damage ?
}
}
psdt; call coroutine as StartCoroutine(ActivateInvincibility());. Don't use string name.
Hello I am making a 2D top down student game in Unity. I am stuck at the animation part where My attack animations lasts for 1 frame and then goes straight back to Idle. Using C# in visual studio:
void Update () {
Move ();
float lastInputX = CrossPlatformInputManager.GetAxis("Horizontal");
float lastInputY = CrossPlatformInputManager.GetAxis("Vertical");
if (lastInputX != 0 || lastInputY != 0)
{
anim.SetBool("Walking", true);
anim.SetFloat("LastMoveX", lastInputX);
anim.SetFloat("LastMoveY", lastInputY);
anim.Play("Walk");
}
else if (CrossPlatformInputManager.GetButtonDown("Fire1"))
{
anim.SetBool("Attacking", true);
//StartCoroutine(Attack());
anim.Play("Attack");
}
else
{
anim.SetBool("Attacking", false);
anim.SetBool("Walking", false);
anim.Play("Idle");
}
float inputX = CrossPlatformInputManager.GetAxis("Horizontal");
float inputY = CrossPlatformInputManager.GetAxis("Vertical");
anim.SetFloat("SpeedX", inputX);
anim.SetFloat("SpeedY", inputY);
}
I'm not sure about this but if the behaviour of CrossPlatformInputManager.GetButtonDown() is the same as Input.GetButtonDown() it will return true during the frame the user pressed down, but it will not return true until the user has released the key and pressed it again.
This means that on the first frame the user pressed the button it will trigger the Attack animation but next frame will return false and trigger the Idle animation.
Also, I'm not sure why are you calling anim.Play() on each animation, the purpose of Animator parameters is to trigger the animation when a given value is present.
Its because the update loop runs on every frame, and on every frame you are setting the animation. Remove the if else from the update loop. In the animator controller you can make transitions so after the attack it goes back to idle, walking, or whatever you want, you do not need to code what happens at the end of an animation.
I'm working with a 3D avatar and it's my first time working with animations. I have already done one which goes from the idle animation to another animation. It does the transition when the value of a slidebar is below 40, here is the code:
public Slider barraAlimento;
void Start()
{
anim = GetComponent<Animator>();
}
void Update()
{
if (barraAlimento.value <= 40)
{
anim.SetBool("IrHambriento", true);
}
else
{
anim.SetBool("IrHambriento", false);
}
}
This works correctly, but my problem is that now I want to do another transition. When I click a button, the value of the slidebar increases (that's how is triggered the previous animation), so I want a transition between the previous animation and the new one when the button is pressed. I have tried this, but it doesn't work:
public Button botonManzana;
void Start()
{
anim = GetComponent<Animator>();
botonManzana.onClick.AddListener(ButtonManzanaClicked);
}
void ButtonManzanaClicked()
{
anim.SetBool("IrComiendo", true);
anim.SetBool("IrComiendo", false);
}
The boxes and arrows are like this, if that's useful information.
Animation transition
I believe you're looking for a trigger rather than a bool.
Change the bool value in your animator from Boolean to Trigger and change your code to...
void ButtonManzanaClicked()
{
anim.SetTrigger("IrComiendo");
}
This will make a transition happen every time you "Trigger" the trigger, like a one time thing, that doesn't require any boolean true -> false for resetting like you're attempting in this code.
The reason your code isn't working, I believe, is because you're re-setting it back to false in the same frame, and I think the animation system will look at the values at the end of each code frame, so to speak.
this is probably happening because in:
void ButtonManzanaClicked()
{
anim.SetBool("IrComiendo", true);
anim.SetBool("IrComiendo", false);
}
you are setting it to false right after you set it to true.
Try putting only anim.SetBool("IrComiendo", true); in the button click event, and anim.SetBool("IrComiendo", false); only when you want it to go back to the "Hambriento" animation
EDIT:
try doing this:
change "IrComiendo" to trigger (just to not need to change its value to false)
OBS: use anim.SetTrigger("IrComiendo"); to call it
set the connections as in the image:
* connection not necessary if its impossible that the value of the slider still smaller than 40 after the button is clicked
** put this connection if you want it to go to Comiendo even if it isnt hambriento
OBS: in the button method you just need change the value of the slider and call "IrComiendo"
hope it helped
Currently I'm simply trying to change the sprites candle from unlit to lit when the player has 'picked up' both the candle and the matches and the candle will 'go out' after a certain amount of time. However, when the space bar is pressed the transition from unlit to lit isn't occurring, even though the debug log is returning true when it should. I'm posting here to get some guidance as I have spent most of the day looking online and literally have no idea how to proceed.
Basically the images I am trying to transition between are two different images which are in the sprites folder under assets.
This is what I've got so far.
//the two sprites transition
public Sprite unlitCandle;
public Sprite litCandle;
private SpriteRenderer spriteRenderer;
bool pickUpMatches = false;
bool pickUpCandle = false;
float timeRemaining =5;
bool candleLit = false;
// Use this for initialization
void Start () {
spriteRenderer = GetComponent<SpriteRenderer>();
if (spriteRenderer.sprite == null)
spriteRenderer.sprite = unlitCandle;
}
// Update is called once per frame
private void OnTriggerEnter2D(Collider2D collision)
{
if(collision.gameObject.CompareTag("Matches"))
{
collision.gameObject.SetActive(false);
pickUpMatches = true;
}
if (collision.gameObject.CompareTag("UnlitCandle"))
{
collision.gameObject.SetActive(true);
pickUpCandle = true;
}
}
public void CandleTimer()
{
if (candleLit == true)
{
timeRemaining = 5;
timeRemaining -= Time.deltaTime;
if (timeRemaining <= 0)
{
candleLit = false;
spriteRenderer.sprite = unlitCandle;
}
}
}
public void ChangeSprite()
{
if (spriteRenderer.sprite == unlitCandle)
{
spriteRenderer.sprite = litCandle;
}
}
void Update () {
if (pickUpCandle == true && pickUpMatches == true)
{
//Debug.Log(candleLit);
if (Input.GetKey(KeyCode.Space) && !candleLit)
{
CandleTimer();
ChangeSprite();
Debug.Log(timeRemaining);
candleLit = true;
//Debug.Log(candleLit);
}
}
}
}
Try comparing with a method like equals() instead of == in
spriteRenderer.sprite == unlitCandle
Because right now you are just comparing references and not the objects.
At least I think thats the problem.
There are a few possible issues with your code. First, you are calling changeSprite at the top of Update, which means that it is unconditionally being called every frame. Therefore, after a single frame of your candle being unlit, it will immediately change its sprite to litCandle.
I assume that the reason you are calling changeSprite every frame is in order to process the timer if you have a lit candle already. Really, you should move the code to process the timer (your whole second if statement in changeSprite) to a separate function and name it something like processCandleTimer. Call that at the top of Update and save the changeSprite method to only be called on the keypress.
Lastly, the issue that I suspect is giving you the most trouble is that you aren't resetting your timer, timeRemaining. The first time you light the candle the timer will go down to 0 after the 5 seconds pass. Every time changeSprite is run after that, you will change the sprite to litCandle in the first if statement and then immediately change it back to unlitCandle because the timer is 0 in the second. To remedy this, you need to add a line like timeRemaining = 5.0f; when the key is hit.
I am creating a 2D platform game with Unity and C#. I searching for how I can do the following.
I have 5 sets of animations and one gameObject(later in game there should be more than one object that can be changed, so maybe we can keep that in mind) with the tag "Campfire0" stored in anim0 inside the start function. What I want is when the user pressed E on his keyboard it will check which is the current animation of the current gameObject and change that animation to "Camfire25" or another number like 50, 75 or 100 and update the gameObject tag. After that is done, it should again check all if statements and the second time you pressed E it should look at the if statement with if(anim25) and so on.
Problem
Below code I use currently. But the problem is the following. I declare inside the start function the animator of each game object tag, but this will be fired one time if the game is started. After pressing the second time on E, the error "NULL" NullReferenceException will occur. So I think I should store the values inside an array? And how should I do that.
For checking which animation is the current one, I use if statements, but can it also be done with a foreach loop or is there a shorter way to do this?
Current Code:
public Animator anim0;
public Animator anim25;
public Animator anim50;
public Animator anim75;
public Animator anim100;
// Use this for initialization
void Start () {
count = 0;
setCountText ();
currentValue = startingValue;
//anim = GameObject.Find("Campfires").GetComponent<Animator>(); // Parent of all Campfires
anim0 = GameObject.FindGameObjectWithTag("Campfire0").GetComponent<Animator>();
anim25 = GameObject.FindGameObjectWithTag("Campfire25").GetComponent<Animator>();
anim50 = GameObject.FindGameObjectWithTag("Campfire50").GetComponent<Animator>();
anim75 = GameObject.FindGameObjectWithTag("Campfire75").GetComponent<Animator>();
anim100 = GameObject.FindGameObjectWithTag("Campfire100").GetComponent<Animator>();
}
void Update () {
if (inTrigger){
if (Input.GetKeyDown(KeyCode.E) && count > 0){
// Update counter on press
updateCount();
if (anim0){
anim0.SetTrigger ("Campfire25");
GameObject.FindGameObjectWithTag("Campfire0").transform.tag = "Campfire25";
}
if (anim25){
Debug.Log ("hello");
anim25.SetTrigger ("Campfire50");
GameObject.FindGameObjectWithTag("Campfire25").transform.tag = "Campfire50";
}
if (anim50){
anim50.SetTrigger ("Campfire75");
transform.tag = "Campfire75";
}
if (anim75){
anim75.SetTrigger ("Campfire100");
transform.tag = "Campfire100";
}
}
}
}
Above script works for the first time, it will change the campfire tag to "Campfire25" and show another animation clip, after pressing E for the second time it will give me an error of NullReferenceException. This is because the Start Function will be fired ones.