I have various powerups in my game that do different things. They are handled through ScriptableObjects for their UI sprites, descriptions, names, duration, etc. They have a begin, tick, and end state. What I'm doing right now is basically checking in the player which name is your currently active powerup, and then doing different things depending on that like moving the player, turning off gravity, etc. I'd like the actual code for each powerup to not be tied in the player script but ScriptableObjects do not have a way to do "custom" code per instance of the ScriptableObject. I think I would have to have a ScriptableObject for the pickup data and then some other script to handle the actual processing. I do not know how to tie them together so the player can find out the logic for the pickup though besides a "powerup solver" that would find whichever script that corresponds to the powerup you have, but that seems not ideal.
-
1\$\begingroup\$ Your pick up effect/logic can be inside the ScriptableObject. Then when a character collects it he can pass itself to a SO method for SO to handle it and apply the desired effect. But still the per instance data should be at the character side. Alternatively there can be say a list inside the SO that strores objects that track the state for each active pickup per character. \$\endgroup\$– NikaasCommented Aug 21, 2021 at 5:50
-
1\$\begingroup\$ I'm not going to post this as a full answer because I'd have to break down what's already on the link github.com/xjjon/unity-flexible-buff-system - Essentially you are creating a new component (I called mine Buffable) this handles adding and removing buffs, if it can be buffed it has this component the buffs themselves are implemented in two parts, a general c# class TimedBuff to handle how when it ticks or stacks buffs and the actual behaviour of a buff is implemented in a scriptableobject class (So I have FrozenDebuff(SO), Burning, Electrocuted etc). \$\endgroup\$– Pheonix2105Commented Aug 21, 2021 at 17:00
-
\$\begingroup\$ All you'd need do is in each Buff Behaviour ScriptableObject, if one such buff disables movement, check there is a motor component, or navmesh agent what have you for this particular unit and disable component/reduce speed etc. This isn't tied to anyone particular controller class, the buffs can simply disable components or adjust stats on the unit its being applied to, regardless if thats a player or AI. \$\endgroup\$– Pheonix2105Commented Aug 21, 2021 at 17:02
2 Answers
One option would be to implement each active powerup as a separate MonoBehaviour which you can attach to any gameObject. That gameObject can be the player, or it can be any other gameObject. So you automatically get the ability for anything to receive powerups, as long as it has has the components that powerup depends on. Not just the player.
So when a gameObject has the "Double move speed" powerup, then you add the "DoubleMoveSpeed" component to said gameObject using AddComponent and later remove it via Destroy. The "Begin", "Tick" and "End State" logic can be moved into the Unity event methods Start
, Update
and OnDestroy
respectively. Those will be called automatically by the engine.
That DoubleMoveSpeed component would of course be dependent on the component which handles movement speed in your game. When you are smart, you don't have a PlayerController
god-object which does everything a player can do, but instead create a separate reusable component for every mechanic. Like a Movement
component which you assign to anything that moves.
I think what you're looking for are Singleton, using this make a PowerManager.cs
(or some name of your liking), then you can reference this Manager throughout your whole game/project.