[WAY OFF TOPIC, BUT I DON’T KNOW WHERE ELSE TO ASK. PLEASE SEE IF YOU CAN HELP ME IN ANYWAY SHAPE OR FORM]
OK so… I’m trying to create an alternative player state machine system, something to avoid entirely confusing between what each system does when the player is on the mount of an animal, compared to when he is on his feet and roaming
First, I created a static class, with a single static variable called ‘isOnAnimalMount’, and went into Malbers’ Rider.cs script and modified it so it considers this script accordingly
Next, I started working on an alternative state machine, and the first thing I decided to do was test the death animations of the player when he is on the back of a horse
Now, I’m not 100% sure what’s going on, but the new state machine did make it to the death state, when an enemy kills my player on the back of a horse, but no animation is played. There are some respawn glitches as well, but that’s something for me to fix after I fix the animation issue
Any idea how to fix this? Here’s what I came up with:
‘AnimalMountManager.cs’ (a single static variable static class:
namespace RPG.Statics {
public static class AnimalMountManager
{
// Similar to DodgeManager, this static class is carefully controlled from multiple scripts
// to make sure the player can act accordingly, and perform other complex operations, based
// on whether the player is mounting an animal or not
public static bool isOnAnimalMount = false;
}
}
then in ‘MRider.cs’, I tuned this variable accordingly
next, I created a new script for the player that’ll switch the state machines, in an Update function, based on whether the player is on an animal or not, as follows:
using RPG.Statics;
using UnityEngine;
using RPG.States.Player;
using RPG.States.PlayerOnAnimal;
public class PlayerToPlayerOnAnimalToggle : MonoBehaviour
{
private PlayerStateMachine player;
private PlayerOnAnimalStateMachine playerOnAnimalStateMachine;
void Awake()
{
player = GetComponent<PlayerStateMachine>();
playerOnAnimalStateMachine = GetComponent<PlayerOnAnimalStateMachine>();
}
// Update is called once per frame
void Update()
{
if (AnimalMountManager.isOnAnimalMount)
{
player.enabled = false;
playerOnAnimalStateMachine.enabled = true;
}
else
{
player.enabled = true;
playerOnAnimalStateMachine.enabled = false;
}
}
}
Then I started creating the state machine, and here is what I came up with so far:
The state machine itself:
using UnityEngine;
using MalbersAnimations.HAP;
using RPG.Animals;
using RPG.Attributes;
using RPG.Movement;
namespace RPG.States.PlayerOnAnimal {
public class PlayerOnAnimalStateMachine : StateMachine
{
[field: SerializeField] public Animal Animal {get; private set;}
[field: SerializeField] public MRider Rider {get; private set;}
[field: SerializeField] public Health Health {get; private set;}
[field: SerializeField] public Animator Animator {get; private set;}
[field: SerializeField] public ForceReceiver ForceReceiver {get; private set;}
[field: SerializeField] public CharacterController CharacterController {get; private set;}
void Start()
{
if (Health.IsDead()) SwitchState(new PlayerOnAnimalDeathState(this));
else SwitchState(new PlayerOnAnimalFreeLookState(this));
Health.onDie.AddListener(() =>
{
SwitchState(new PlayerOnAnimalDeathState(this));
});
Health.onResurrection.AddListener(() =>
{
SwitchState(new PlayerOnAnimalFreeLookState(this));
});
}
void OnValidate()
{
if (Rider == null) Rider = GetComponent<MRider>();
if (Health == null) Health = GetComponent<Health>();
if (Animator == null) Animator = GetComponent<Animator>();
if (ForceReceiver == null) ForceReceiver = GetComponent<ForceReceiver>();
if (CharacterController == null) CharacterController = GetComponent<CharacterController>();
}
void OnEnable()
{
// You can't get the animal in 'Awake', since it's dynamic, so I decided to do the work in 'OnEnable', since this is a toggleable script
Rider = GetComponent<MRider>();
Animal = GetComponentInParent<Animal>();
}
void OnDisable()
{
// To delete the changes when the script is turned off
ClearAnimal();
ClearPlayerRider();
}
void ClearAnimal()
{
Animal = null;
}
void ClearPlayerRider()
{
Rider = null;
}
}
}
the base state:
using UnityEngine;
namespace RPG.States.PlayerOnAnimal
{
public abstract class PlayerOnAnimalBaseState : State
{
protected PlayerOnAnimalStateMachine stateMachine;
protected float AnimatorDampTime = 0.1f;
public PlayerOnAnimalBaseState(PlayerOnAnimalStateMachine stateMachine)
{
this.stateMachine = stateMachine;
}
protected void Move(float deltaTime)
{
Move(Vector3.zero, deltaTime);
}
protected void Move(Vector3 direction, float deltaTime)
{
stateMachine.CharacterController.Move((direction + stateMachine.ForceReceiver.Movement) * deltaTime);
}
protected float GetNormalizedTime(string tag = "Attack")
{
var currentInfo = stateMachine.Animator.GetCurrentAnimatorStateInfo(0);
var nextInfo = stateMachine.Animator.GetNextAnimatorStateInfo(0);
if (stateMachine.Animator.IsInTransition(0) && nextInfo.IsTag(tag))
{
return nextInfo.normalizedTime;
}
else if (!stateMachine.Animator.IsInTransition(0) && currentInfo.IsTag(tag))
{
return currentInfo.normalizedTime;
}
return 0; // return something
}
}
}
freelook (for now. It sounds pointless to me in this coniditon tbh):
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace RPG.States.PlayerOnAnimal {
public class PlayerOnAnimalFreeLookState : PlayerOnAnimalBaseState
{
public PlayerOnAnimalFreeLookState(PlayerOnAnimalStateMachine stateMachine) : base(stateMachine) {}
public override void Enter()
{
Debug.Log($"PlayerOnAnimalFreeLookState entered");
}
public override void Exit()
{
}
public override void Tick(float deltaTime)
{
}
}
}
and then death, where I’m doing all the testing (again, the debugger says it gets here, but the animations are not played at all):
using RPG.States.PlayerOnAnimal;
using UnityEngine;
public class PlayerOnAnimalDeathState : PlayerOnAnimalBaseState
{
public PlayerOnAnimalDeathState(PlayerOnAnimalStateMachine stateMachine) : base(stateMachine) {}
private static readonly int PlayerOnAnimalDeathHash = Animator.StringToHash("PlayerOnAnimalDeath");
public override void Enter()
{
Debug.Log($"PlayerOnAnimal Entered Death State");
stateMachine.Animator.CrossFadeInFixedTime(PlayerOnAnimalDeathHash, AnimatorDampTime);
}
public override void Tick(float deltaTime)
{
Move(deltaTime);
}
public override void Exit() {}
}
that’s all I did so far. If anyone knows what I should do next, please let me know
my main problem is that it does not play any animations