I have a model not my own one that with a script I loop over the root main model and all it’s children and turn on/off all the Animators. The game start when all the animators are disabled so the model is turned off.
This script is attached to the model :
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class AnimFlyertransportationController : MonoBehaviour
{
public GameObject JetFlame;
public bool turnOffOn = false;
// Start is called before the first frame update
void Start()
{
TurnAllAnimtorsOff(transform, turnOffOn);
if (turnOffOn)
{
JetFlame.SetActive(true);
}
else
{
JetFlame.SetActive(false);
}
}
private void TurnAllAnimtorsOff(Transform root, bool onOff)
{
Animator[] animators = root.GetComponentsInChildren<Animator>(true);
foreach (Animator a in animators)
{
if (onOff)
{
a.enabled = true;
}
else
{
a.enabled = false;
}
}
}
private void OnValidate()
{
TurnAllAnimtorsOff(transform, turnOffOn);
if (JetFlame) JetFlame.SetActive(turnOffOn);
}
}
I mean your Jet Frame is On right, aren’t you supposed to be up in the air?
if you turn off which animation take your Flyer back down then. if there no landing going on then your Flyer is going keep up and up
I tried something and got a bit messed with the bool flags.
I did that the default state machine when the game start will be takeoff but the animators also will be disabled :
The spacecraft is on the ground when the game start :
Now when the game is running and I set the flag Turn On Off to be true it will start the spacecraft and also will move it up smooth as taking off :
Now when I set the Land flag to true I want it to play the landing animation and also turn off all the animators and the engine. It’s landing but not turning off the animators and engine and if I’m doing :
Then it’s turning everything off but the spacecraft never land.
I want that with one bool it will turn on and take off and with the second bool it will land first then turn everything off and so on. maybe even to do it with one bool. but now I messed all the flags.
all you need to do is to check when “Anim_Flyer_Land” is finished, for right now you are force to enables animator before land animation even finish it.
write a logic that wait for landing animation to finished first then turn it all of.
I tried this the checking script if the animation still playing :
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CheckAnimationEnd : MonoBehaviour
{
public GameObject _animator;
public string animStateName;
private Animator _ani;
// Start is called before the first frame update
void Start()
{
_ani = _animator.GetComponent<Animator>();
}
// Update is called once per frame
void Update()
{
if (animStateName != null && animStateName != "" && _ani != null)
IsPlayingAnimation();
}
public bool IsPlayingAnimation()
{
bool IsOffLand = false;
if (_ani != null)
{
if (!_ani.GetCurrentAnimatorStateInfo(0).IsName(animStateName))
{
IsOffLand = true;
}
else
{
IsOffLand = false;
}
}
return IsOffLand;
}
}
And then :
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class AnimFlyertransportationController : MonoBehaviour
{
public GameObject JetFlame;
public CheckAnimationEnd checkAnimEnd;
public bool turnOffOn = false;
private Animator[] animators;
// Start is called before the first frame update
void Start()
{
TurnAllAnimtorsOff(transform, turnOffOn);
if (turnOffOn)
{
JetFlame.SetActive(true);
}
else
{
JetFlame.SetActive(false);
}
}
private void TurnAllAnimtorsOff(Transform root, bool onOff)
{
animators = root.GetComponentsInChildren<Animator>(true);
foreach (Animator a in animators)
{
if (onOff)
{
a.enabled = true;
}
else
{
a.enabled = false;
}
}
}
private void OnValidate()
{
TurnAllAnimtorsOff(transform, turnOffOn);
if (JetFlame) JetFlame.SetActive(turnOffOn);
Land();
TakeOff();
}
private void Land()
{
if (turnOffOn == false)
{
checkAnimEnd.animStateName = "Anim_Flyer_Takeoff";
animators[0].Play("Anim_Flyer_Land");
if (checkAnimEnd.IsPlayingAnimation())
{
TurnAllAnimtorsOff(transform, false);
JetFlame.SetActive(false);
turnOffOn = false;
}
}
}
private void TakeOff()
{
if(turnOffOn)
{
checkAnimEnd.animStateName = "Anim_Flyer_Land";
animators[0].Play("Anim_Flyer_Takeoff");
if (checkAnimEnd.IsPlayingAnimation())
{
TurnAllAnimtorsOff(transform, true);
JetFlame.SetActive(true);
turnOffOn = true;
}
}
}
}
but everything is messed now. when I set the TurnOffOn to be true the spacecraft start from up and land and then when set it false it’s taking off and everything turn on/off the animators and fire I messed all the flags and both scripts.
This is working great. The other problem I see now is when the game start the object is on the ground but when setting the TurnOffOn to true the spacecraft move up then when set to false it’s moving down but not to the ground as before it stay a bit above the ground.
Now sure if it’s easy if at all to solve because it looks like when it’s taking off it’s first changing position a bit up then take off and then when landing the animation stop when the spacecraft is a bit above the ground.
Your flyer has a parent, make sure your flyer local space Y position is on the correct position. if it still didn’t fix then check the animation clip origin.
if it was animation clip origin then You can fix by editing the first animation’s key in TakeOff Animation Clip and the last key in Landind Animation Clip.
that are one of the many con of using root animation
root animation you will end up writing a lot of code just to make it feel right and the code can get very easy messy and you already see it by yourself.
I’m not biased against root animation, but for me it is easier and lesser problems to just procedural animate with code for a simple transition, because it’s real time dynamic.