Getting PlayerBaseState to refer to 2 Animators connected to Player GameObject?

Hi!

I’m trying something a bit different from this course. I made my own Male and Female models and want the player to be able to choose between either one. They have different Avatars and will have different sound effects and animations, but will have the same controls and speed.

When setting up my Player, I made an empty GameObject and called it Player, then I stuck my Male and Female models (Player M and Player F) into that. So far so good.

That is, until I need to implement [field: SerializeField] public Animator Animator { get, private set; } to my PlayerBaseState. I can only pair one Animator to this, not two.

Right now if I make a third Player Animator and give it no Avatar, it conflicts with the two Animators I have set up under my M and F players (weird effects, I can link a video if you’d like).

How would I go about being able to pair both my Male and Female’s Animators? I was thinking of putting in something like GetComponentInChildren in my PlayerStateMachine, but am unsure of how to go about doing that without getting other errors.

Please let me know if I need to copy/paste my code.

Edit: I updated my PlayerBaseState to include //public Animator Animator; instead of the [SerializeField], and added Animator = GetComponentInChildren< Animator >(); Ideally, this would have worked. The parent Player object inherited the proper Player model’s animator, but I’m still having the same issue as before, where the player will move weirdly. (Animator doesn’t have space in between carrots in code, _ will cross out but < test > will stay)

In terms of switching between the 2 animators… try something like this:

[field: SerializeField] public Animator MaleAnimator {get; private set;}
[field: SerializeField] public Animator FemaleAnimator {get; private set;}  
public Animator Animator {get; private set;}

public void SetGender(bool male)
{
    Animator = male ? MaleAnimator : FemaleAnimator;
}

presuming that the Animators are the on the top GameObject for each of the Models, you could even use this method to take care of the models:

public void SetGender(bool male)
{
    Animator = male ? MaleAnimator : FemaleAnimator;
    MaleAnimator.gameObject.SetActive(male);
    FemaleAnimator.gameObject.SetActive(!male);
}

I put your above code at the bottom of my PlayerStateMachine script. This helped with the movement issue, but now I’m back to a previous issue I had, which is that, while the player controls fine, the character itself doesn’t animate (outside of its idle pose). This is the same problem I had when I would leave the Animator field empty, and kept my Player Animators on.

Previously when the player would move weird, it would still animate the running and rotate.

Right now, Unity gives me two “NullReferenceException: Object Reference not set to an instance of an object” errors when I play the game (good news, I can play the game). These are located in my PlayerFreeLookState.Tick and StateMachine.Update.

FreeLook script line

stateMachine.Animator.SetFloat(FreeLookSpeedHash, 0, AnimatorDampTime, deltaTime);
return;

StateMachine script line

[field: SerializeField] public Animator MaleAnimator { get; private set; }

Would it help if I sent over my whole scripts?

If SetGender is being called, then the Animator should be set… If it’s null, are you sure you’re calling SetGender?
Add this debug into SetGender, at the end of the script:

Debug.Log($"animator set to {Animator.gameObject.name}");

Even after I add the debug at the bottom of my SetGender public void (does it need to be it’s own script?), I still have the same issues, and the debugger won’t show up. I must have done something wrong, but can’t figure out what it could be.

 [field: SerializeField] public Animator MaleAnimator {get; private set;}
 [field: SerializeField] public Animator FemaleAnimator {get; private set;}
 public Animator Animator {get; private set;}
 public void SetGender(bool male)
        {
            Animator = male ? MaleAnimator : FemaleAnimator;
            MaleAnimator.gameObject.SetActive(male);
            FemaleAnimator.gameObject.SetActive(!male);
            Debug.Log($"animator set to {Animator.gameObject.name}");
        }

You need to call set gender from somewhere… probably in the script that allows the character to set the Gender… If it’s in a menu scene… then you’ll probably need to store that choice in player preferences and then in PlayerStateMachine.Awake() call SetGender with the result of the choice in player preferences.

Gotcha! I’m not that far in my game development yet so for now, I was hoping for a solution where I could switch to and from them by just deactivating and reactivating whichever one I felt like testing with.

I’ll implement a quick character select menu at the start, and hopefully my player should move well. Thanks for being so responsive! I’ll be back sooner or later.

You actually could do that… by putting a component on the same GameObject as the Animator, which then called the StateMachine in OnEnable() and called SetGender()

1 Like

Hi! I’m coming back about a week and a half later having almost built a Player Rig that can house multiple player models. However, attaching a parent Player object to the Player Rig, and then attaching the PlayerF and PlayerM models to the parent Player object has proven to be bit easier said than done.

The first and easiest step was moving the CameraFocus and Targeter from the model to the Player parent object.
bandicam 2023-01-17 15-36-57-511

I attached virtually every script to the Player parent object, and only assigned the Weapon Handler script to each model.


They get the Animator and the Weapon when the game is played.

This is because I added

public Animator Animator;

and

public WeaponDamage Weapon;

to the public class PlayerStateMachine : StateMachine

and I added

Animator = GetComponentInChildren<Animator>(); //Part of Rig Setting
        Weapon = GetComponentInChildren<WeaponDamage>(); //Part of Rig Setting

to the private void Start() of the PlayerStateMachine.

2 problems come up.

The first is that in the CinemachineStateDrivenCamera in the Player Rig, it requires an Animated Target to be assigned in order to work. I am trying to figure out a way to have this automatically assigned depending on which Animator is active (or on top if both M and F are active). So far, I have not been able to figure out how to accomplish this.

The second problem I have is about the WeaponDamage. For this rig to work as it is now, I must leave active the WeaponLogic on my PlayerF and PlayerM
bandicam 2023-01-17 15-52-00-252
This is because if I leave it off and attack, I get these error messages.


If I leave it on, it works. However, the WeaponLogic stays active until the Player attacks for the first time, then it turns off and on as it should. How can I start the game with the WeaponLogic inactive, and have it work at the same time?

I feel like I’m SOOOO close to getting this right, if it weren’t for these two issues I can’t seem to solve.

While I don’t recommend this particular approach in favor of spawning a player in at runtime with the selected model, these two problems remain the same in both cases.

For the Camera, you need a reference to the CinemachineStateDrivenCamera.

stateDrivenCamera.m_animatedTarget = Animator;

For the WeaponLogic, Leave it on, and find it at runtime after finding the active Animator with Animator.GetComponentInChildren<WeaponLogic>();

This may sound like a noob question but what scripts should I enter those in to? Tried the private void Start() in the PlayerStateMachine but it didn’t like that.

It should have liked that… as long as the correct objects have been activate/deactivated… otherwise, a brute force method may be needed for both.

My gut tells me I missed something or didn’t comment the right stuff out. It’s telling me the name stateDrivenCamera doesn’t exist in the current context.
bandicam 2023-01-18 10-54-44-345

Update, I tried WeaponDamage because WeaponLogic got the red squiggly lines too. The error says that the type or namespace ‘WeaponLogic’ could not be found.

You would need a reference to the state driven camera, either set in the inspector or with a FindObjectOfType.
I think Weapon Logic, that was based on your previous post, the WeaponLogic Game object, use whatever the class name is. You’re right, though, in the course it’s WeaponDamage.

For whatever reason nothing seems to want to work. Been trying different ways to type it out, including this.

    Cinemachine stateDrivenCamera.m_animatedTarget;

    private void Start()
    {
        Animator = (Animator)FindObjectOfType(typeof(stateDrivenCamera.m_animatedTarget));
        
        
        //Animator.GetComponentInChildren<WeaponDamage>();
        Animator = GetComponentInChildren<Animator>();
        Weapon = GetComponentInChildren<WeaponDamage>();

I commented out that line because for some reason it didn’t work with my build (have no idea why, the two lines look nearly identical)

All instance of the stateDrivenCamera.m_animatedTarget = Animator; come up with the red lines too.

Also, (after further testing and looking at the Debug menu further) it looks like the Weapon bug only affects each enemy one time and doesn’t deal any damage, just impacts them for a bit. I may require the player to break out of a barrier each level to hide that bug if i can’t fix it haha.

CinemachineStateDrivenCamera stateDrivenCamera = FindObjectOfType<CinemachineStateDrivenCamera>();
Animator = GetComponentInChildren<Animator>();
Weapon = Animator.GetComponentInChildren<WeaponDamage>();
stateDrivenCamera.m_AnimatedTarget = Animator; //Edited

Thank you so much! That got me a lot closer, but I’m still not there yet. Originally I got some error messages.

I wound up adding using Cinemachine; to the top, and that got rid of some swiggly lines under the CinemachineStateDrivenCamera. Now the only error I’m getting is under the m_animatedTarget. It’s giving me this error message.


I must be missing something I should have had awhile ago (I missed the using Cinemachine; at the top afterall lol).

Update. SOLVED IT. I had to make it stateDrivenCamera.m_AnimatedTarget = Animator;

I’m still having the minor issue with my Weapon Logic still staying on unitl the player’s first swing, but that’s a very minor bug. Thank you so much for helping me through this!

Oops, typo on my part. Sorry about that.

No problem at all, it was a great learning experience.

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.

Privacy & Terms