Forum rules - please read before posting.

Implementing seasonal events

edited January 2022 in Technical Q&A
Hey guys,

I'm trying to implement some seasonal events in my game. I want my character to be dressed like santa claus if you play it in december.

So, using playmaker I was able to have an FSM to get system dateTime and export it to a substring with the month digits only and connect it to an AC variable, so I can check if its "12" or not inside AC.

So, the next step for that would be creating a system where - based on that variable's value - I could control the animator to show either the normal animations or the santa claus ones.

I've read a lot of posts on the forum about that, but I still don't know how to accomplish this. If I'm gonna use a base animator layer for the normal character and a sub-layer to the santa claus one.. then I wouldn't know how to call this change in AC or even in Unity.. maybe from script only? (I don't know how to code).

I should mention also that I managed to make this work through playmaker.
I created a FSM that gets the month and - if it is 12 - sets the sub-layer's weight to 1.
Pretty close to what I wanted.

However I have 2 questions about it:

1. I'm getting playmaker to run this indepently from AC, which I found weird because I thought I had to call this from AC "third-party > playmaker" action to make this happen. Is there any problem having PM handle this like that?
2. The best scenario for me would be setting the character before the game starts (in some starting menu scene).
If I could modify the character's prefab to affect all instances of it, then it would be perfect, since I wouldn't have to rely on PM anymore nor keep checking for the month variable to animate this guy.

Plus.. I wanted this change to happen only before loading scenes where this character appears - as a game design decision also - cause if you're playing with the character and it suddenly changes the outfit.. well this is not what I intended...

The concept I want to implement is like..
Ok say you're playing the game in november 30th and while you play it you enter december.. then.. I want the character to stay normal and only update to santa claus in the next load game...
This is a narrative thing.. since this character has 2 jobs.. he works as a mechanic normally.. but as a santa claus in december. So if you visit him another day (load game) then maybe he'll be home after this other job.. you follow me?
crazy talk right?

In other words.. is there a way to set the character before loading his scenes?

Ps.: I would rather rely on PM for the month thing only. If I could do the animation part on AC it would be much better for me, cleaner I mean.. but I don't know how to call for animator layer changes in AC.

Can you help me?

Sorry for the big text...

Comments

  • Another solution I thought is to have 2 different gameobjects for the character (one for the normal one - visible in the scene - and one for the santa claus - hidden offscreen). Then, if the month variable is 12 I simply teleport the santa claus to show in the scene and teleport the normal to hide.

    Since they both share the same variables and hotspots this would work even better then the previous solution.. since I would swap animator controllers and animations without having to adjust the standard animations in addition to that..

    But yeah.. it would involve checking the month variable everytime I animate this npc. So.. i don't know..
  • However you update the Player's appearance, whether or not you have to do so every scene depends on whether or not you're making use of local Player objects in those scenes, or spawning them in via the Settings Manager's "Player prefab" field.

    If you spawn them in, you can make the change once and be done with it - any changes you make to their Animator's sub-layer's weight will be carried over to the next scene. That is, unless that new scene makes use of a local Player object - in which case the spawned Player prefab is removed.

    How you affect the Animator layer's weight isn't too important. There isn't a built-in AC Action to do this, so you'd have to end up either relying on a custom script for this, or the use of Playmaker. Either method will result in the same effect, though.

    The main thing is to call this at the right time. I'd advise creating a special scene to handle this change that keeps the Player hidden, and runs before the Player is seen.

    The other solution, as you mention, is to rely on a separate Player object. For this, you can rely on AC's Player-switiching system, as covered in this tutorial.

    With this approach, you'd create a second Player prefab with the updated appearance, and have both prefabs assigned in the Settings Manager. In this "set up" scene, you could then run the Variable: Check Action followed by the Player: Switch Action to set the correct Player based on the variable's value. Just be sure to check Replace old Player's position? so that the new Player prefab replace the old one's position, as opposed to having the game switch to wherever their default scene is.

  • edited January 2022
    Thanks for the quick response @ChrisIceBox
    I think I follow you.. but sorry I didn't made it very clear.. the character is a NPC.. not a player..
    Can I do the same things with him being a NPC?

    My game has no player.. it's supposed to be a 2d first person with no player on screen. So since we're talking about it I'll ask an old question I had about it.
    Can i have a game with no player and npcs that behave like inactive players? That sure would be perfect cause like you said I would be able to use AC player resources for spawning.

    The whole problem comes from the character being a NPC.
  • edited January 2022
    Maybe I could make him a player but constrain his movement for the most part of the game so when it moves would be indirectly through actions in cutscenes (like move to point)? That would solve a lot of issues.. is that doable?
  • The active Player can be prevented from moving due to the user's input by setting the Movement method to None.

    The character in this case need not be the active Player, however. An inactive Player is essentially the same as an NPC, so yes - you can make him a Player but not have him be the "active" Player.

    If you rely on this technique, though, you will have to have an active Player assigned. If you don't want a Player to be visible/controllable, you can just attach a Player component to an empty GameObject and make it a prefab.

    When dealing with inactive Players, AC handles their scene/position internally - so you'll need to remove the character in question from the scene, assign them as a non-default Player, and then edit their "starting data" beside their prefab name in the Settings Manager. It's here that you can tell AC to place them in the scene again.

    To update an inactive Player's position, you can use the Player: Teleport inactive Action.

    The issue with this technique when applied to an inactive Player, however, is that any Actions involved with them is no longer tied to a single character. Given that, I'd say it's probably easier to go with a single regular NPC as before, and update their appearance.

    This could be done through scripting, but I'd need more details to assist. If this is an NPC, do they appear in just one scene, or across several? What is the name/type of the Global Variable involved, and what is the name of the Animator layer it affects?

  • Oh interesting @ChrisIceBox !
    Well, the npc appears in 2 scenes.
    The global variable involved is called "month" and is a string variable.
    The name of the animator base layer is "normalSimon" and the sublayer is "santaSimon".
  • Actually, he appears in 3 scenes.. but this third one is not interactive, is the final cutscene of the game...
  • edited January 2022
    I was wondering if I can solve this by duplicating each scene he appears... this way I would have something like scene1/scene1b, scene 2/scene2b.
    Then I modify scene1b, scene2b etc. by replacing the gameobject normalSimon with santaSimon.
    Then to load the correct scene I would just check (in the previous scene whatever that is) the variable "month" before switching scene.

    This way I wouldn't have to deal with layers or teleporting gameobjects or setting standard animations (I'm trying to keep the onstart actions to a minimum since the scenes in question are very crowded with actionlists running in parallel - so I'm trying not to exceed 10 subsequent actions, as informed in the manual).

    Would that be a good practice?
  • edited January 2022

    I've never tried something like this before, but my first idea would be to create two animator controllers, one with normal animations and another with santa counterparts, and then write a simple script to check the month variable and, if 12, swap the controller in the animator component. Just make sure you declare a public "santa animator" so you can assign it in the inspector.

  • Try this:

    using UnityEngine;
    
    public class SwapAnimator : MonoBehaviour
    {
    
        public RuntimeAnimatorController santaAnimator;
    
        void Start()
        {
            if (AC.GlobalVariables.GetIntegerValue(0) == 12)
            {
                this.GetComponent<Animator>().runtimeAnimatorController = santaAnimator;
            }
        }
    
    }
    

    Just make sure to change the number of the global variable to the one you're actually using. Attach it to the gameobject that contains the NPC's animator (generally the sprite object), assign the alternate controller, and you're good to go.

  • edited February 2022
    Wow this is amazing @Rairun !!! Thank you so much!!
    So, newbie question... when you tell me to change the number of the global variable on the script you mean the variable id? And if so.. do I replace this 0 on the script with the variable id?

    Thanks again!!!
  • The "0" in the script refers to the variable's ID, yes - you would replace this with the number to the left of your "Month" variable.

    If it's a String variable, whose value is "December" when the change should occur, then you'll need to instead replace that line with:

    if (AC.GlobalVariables.GetStringValue (0) == "December")
    

    Again, replacing "0" with the correct ID.

  • Thanks @ChrisIceBox !!
    A few questions though..

    1. Am I supposed to attach the santaAnimator to the npc's sprite child? I can't seem to attach 2 animators in the same gameobject (wouldn't this be a case of using an animator override controller?)

    2. This script would check the variable like a check action in an on start cutscene would do? And if so, does it count as a subsequent action running in parallel?

    3. Would I have to set the standard animations for this new controller? Or if I just use the exact same names for the animations AC will do the change automatically?

    Thank you!
  • edited February 2022
    Oh and 4. Can I use "12" instead of "december" in the string value? Because this is the format I get from the dateTime...
  • Am I supposed to attach the santaAnimator to the npc's sprite child? I can't seem to attach 2 animators in the same gameobject (wouldn't this be a case of using an animator override controller?)

    It's not my script, but it involves replacing the Animator Controller field inside a single Animator component. It should be attached to the same GameObject as the Animator.

    This script would check the variable like a check action in an on start cutscene would do? And if so, does it count as a subsequent action running in parallel?

    It'll run in Start, so it'll run when the scene begins alongside any other startup process.

    Would I have to set the standard animations for this new controller? Or if I just use the exact same names for the animations AC will do the change automatically?

    If your character's "Animation engine" is set to "Sprites Unity", then the animations will play so long as the names match.

    Another approach would be to have two sets of animations in the same Animator for each standard type (e.g. "Normal_Idle" and "Santa_Idle") and have the script instead update the NPC component to play those different sets.

    Can I use "12" instead of "december" in the string value? Because this is the format I get from the dateTime...

    Yes.

  • Thank you guys, I'm gonna run a few tests..
  • edited February 2022
    So the most simple solution that I got working was to just make different animations for both character variations and stick it all in the same animator controller.

    Then before animating him I'll check the month variable and then branch it to the respective popup switch and then play the correct animations.

    A detail here is that this month variable is not the one that is linked with playmaker, since I need to check the real month information on the menu only.

    So I've got now monthOnLine (which is linked with PM) and monthOffLine that will run inGame.

    Thank you guys for all the support I think it will work now!
Sign In or Register to comment.

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Welcome to the official forum for Adventure Creator.