Infinity PBR by Magic Pig Games
  • Infinity PBR Documentation
  • Game Modules 4
    • ➡️Quick Start
    • 📽️Video Tutorials
      • Quick Start: Creating Game Module Objects
      • Automating Start Actions on GameModulesActor
      • Inflicting Damage with Conditions
      • Updating UI (and more) with Blackboard Notes
      • Dynamic Menus with Item Objects and Dictionaries
      • Create Custom Quest Rewards
      • Save and Load Game Data
      • Stats: Deep Dive
      • Items: Deep Dive
      • Conditions: Deep Dive
      • First Person Movement
      • Tutorial: "Overheal" Effect with Condition & Stats
      • Tutorial: Create a Character & Actor Class Inheriting from GameModulesActor
    • 👀Game Modules Viewer
      • Viewer: Dictionaries
      • Viewer: Stat / GameStatList
      • Viewer: ItemObject / GameItemObjectList
      • Viewer: ItemAttribute / GameItemAttributeList
      • Viewer: Condition / GameConditionList
      • Viewer: Quest / GameQuestList
    • V4 Migration Tips
      • Introducing GameModulesActor
      • Interfaces
      • No More Tick*
      • Dictionaries
      • Repositories
      • Tips from Upgrading "Legend of the Stones"
    • Important Information
      • Game Modules Overview
      • Inherit from GameModulesActor
      • Things to not forget to do
      • Bugs, Backups, and Demos
      • FAQ / Tips & Tricks
      • Required Prefabs
      • Game Module Repository
      • Release Notes
    • Module Documentation
      • Game Modules Actor
      • Game Module "Lists"
        • Get() Methods
          • GameStatList Get() Methods
          • GameItemObjectList Get() Methods
          • GameItemAttribute Get() Methods
          • GameConditionList Get() Methods
          • GameQuestList Get() Methods
        • Contains() Methods
          • GameStatList Contains() Methods
          • GameItemObjectList Contains() Methods
          • GameItemAttributeList Contains() Methods
          • GameConditionList Contains() Methods
          • GameQuestList Contains() Methods
        • Count() Methods
          • GameStatList Count() Methods
          • GameItemObjectList Count() Methods
          • GameItemAttributeList Count() Methods
          • GameConditionList Count() Methods
          • GameQuestList Count() Methods
        • Remove() Methods
          • GameStatList Remove() Methods
          • GameItemObjectList Remove() Methods
          • GameItemAttributeList Remove() Methods
          • GameConditionList Remove() Methods
          • GameQuestList Remove() Methods
        • GameStatList
        • GameItemObjectList
        • GameItemAttributeList
        • GameQuestList
        • GameConditionList
      • Blackboard
        • Blackboard.cs
        • Blackboard Follower
        • Blackboard Note
        • Blackboard Event
        • Blackboard Values
        • Tips & Tricks
          • Use extension methods to check BlackboardNotes (or events)
      • Stats
        • IHaveStats
        • Stat.cs
        • GameStat.cs
        • GameStatList.cs
        • Mastery Levels
      • Loot
        • LootItems.cs
        • LootBox.cs
        • GameLootBox.cs
        • Generating & Handling Loot
        • Custom Loot Generation Algorithm
      • Items
        • ItemObject.cs
          • Manage Item Objects
          • Allowed Item Attributes
          • Starting Item Attributes
          • Item Attribute Variables
            • Variables Methods
        • GameItemObject.cs
        • GameItemObjectList.cs
        • ItemAttribute.cs
          • Manage Item Attributes
          • General Settings
          • Name Settings
          • Requisite Attributes
        • GameItemAttribute.cs
        • GameItemAttributeList.cs
        • Code Examples
      • Conditions
        • Condition.cs
          • Main Settings
          • Condition Time
          • Effects on Points
        • GameCondition.cs
        • GameConditionList.cs
        • Expiration Condition Handler
        • Code Examples
      • Quests
        • Quest
          • Main Settings
          • Quest Step Settings
        • Quest Steps
        • Quest Conditions
          • Create a Custom Quest Condition
            • Your Quest Condition
            • Your Quest Condition Editor
            • Your Quest Condition Drawer
          • Quest Condition Details
            • Blackboard Value Bool
            • Blackboard Value GameObject
            • Blackboard Value Number
            • Blackboard Value String
            • Final Stat Is
            • Game Condition List Contains
            • Game Item Object List Contains
            • Game Stat List Contains
          • Quest Condition Enums
        • Quest Rewards
          • Create a Custom Quest Reward
            • Your Quest Reward
            • Your Quest Reward Editor
            • Your Quest Reward Drawer
          • Quest Reward Details
            • Point Reward
            • Condition Reward
            • Quest Quest Reward
            • Item Object Reward
          • Custom Quest Reward Handler
        • GameQuest
        • GameQuestList
        • Quest Events
        • Demo Scene Quests
          • Push the Button
          • Add Money
          • Don't Get Poisoned
          • Rescue the Puppy
      • Voices
        • Voices
        • Voice.cs
        • Code Examples
      • Dictionaries
        • Dictionaries Setup
        • Dictionaries Methods
        • KeyValue Methods
        • Save and Load
        • Object Reference
      • Gametime & Timeboard
        • Timeboard
          • Timeboard Events
          • TimeboardFollower
        • Gametime
          • Pause Level
          • Time Options
          • Properties & Methods
        • TimeSpan
        • Code Examples
      • Property Code
      • Lookup Table
      • Save and Load
        • GameList & GameFile
        • Making objects saveable
        • Saving, and Loading
        • BlackboardEvents sent by Save and Load
    • Game Module "Systems"
      • Drag-and-Drop Inventory System
        • Scripts
          • PanelManager
          • OnScreenItem
          • Panel
          • BoxManager
        • Scene & Class Setup
        • Item / Object Setup
        • Item / Inventory Setup
        • Box Setup (Chests, Bags, Other Inventories)
        • Setup Your Scene
      • First Person Movement
      • Character Creation
    • Game Module Demo Projects
      • Party Based RPG
        • Title Scene
        • Character Creation Scene
        • World & Dungeon Scenes
    • Magic Time for Game Modules
  • ✨Northstar Tracking System
    • ✅Overview & Quickstart
      • ➡️Quick Start
      • 🫐Demo Scene
      • 🛠️Customizing & Overriding
        • Create a Custom Navigation Bar
        • Create a Custom Compass / Radar
        • Runtime Overrides
          • Screen & Edge Overlay
          • Navigation Bar
          • Compass / Radar
      • ☄️Tips & Code Examples
    • Northstar Documentation
      • Global Northstar Settings
      • Northstar Overlay Settings
      • Compass & Radar
        • Compass
        • Radar
      • Northstar Screen Overlay
        • Screen & Edge Overlay
        • Navigation Bar
      • Tracked Target Compass Radar
      • Tracked Target Overlay
        • Types
        • Override Values
      • Overlay Icon
      • Compass Icon
      • Distance Text
  • 🚀Projectile Factory
    • 👀Overview & Quickstart
      • ➡️Quick Start Guide
        • Create Your First Projectile
        • Add Projectile Factory & Create a Projectile Spawner
        • Use 3rd Party Integrations
        • Extending Projectile Factory
        • Making Lasers & Similar Attached Projectiles
      • 💡FAQs + Important Reminders
    • Game Modules 4 Integration
      • Projectiles with TimeMod
    • Magic Time for Projectile Factory
    • ✅3rd Party Particle Integrations [16]
      • ▶️Archanor VFX [5]
        • Sci-Fi Arsenal
        • Polygon Arsenal
        • Magic Arsenal
        • Retro Arsenal
        • Rainbow Magic
      • ▶️Gabriel Aguiar Prod [2]
        • Unique Projectiles Vol. 1
        • Unique Projectiles Vol. 2
      • ▶️HOVL Studio [4]
        • Toon Projectiles
        • Toon Projectiles 2
        • AAA Stylized Projectiles Vol. 1
        • AAA Projectiles Vol. 2
      • ▶️kripto289 [1]
        • Realistic Effects Pack 4
      • ▶️FORGE3D [1]
        • Sci-Fi Effects
      • ▶️Knife [1]
        • PRO Effects - Sci-Fi Shooter FX
      • ▶️Jean Moreno [1]
        • Cartoon FX Remastered
      • ▶️Synty Studios [1]
        • 🟡Synty Studios Particles
    • Projectile Factory Documentation
      • 🔫Projectile Spawner
        • Projectile Spawner Code
      • 🚀Projectile
        • Projectile Code
        • Projectile Data
      • ✨Spawn Behavior
        • Spawn Behavior Code
        • Spawn Behavior Modification
      • 🕊️Behaviors
        • Behavior Examples
      • ⚡Events
      • 👁️Observers, Global Observers, and Observer Objects
        • Toggle Objects At Events Observer Object
      • 👩‍💼Factory Manager
      • 🏹Trajectory
      • 🎱Object Pooling
      • 🤩Create Custom Behaviors
      • Spawn Point Manager
      • Helper Tools
        • Projectiles Quick Editor
        • Set Trail Auto Destroy to False
        • Set Layer of All Projectiles
        • Remove Colliders
      • Additional Scripts
        • Destroy or Pool Object
        • Project Force
        • Raycast Shooter + Handlers
        • Projectile Utilities
  • Additional Systems & Tools
    • 🎨Runtime Color Sampler
      • Quick Start
      • Demo Walkthrough
      • Runtime Color Sampler (Prefab & Class)
        • Sampler Sphere
        • Sampler Camera
      • Runtime Listener
      • Runtime Color Settings
      • Scripting
      • Additional Classes
    • 🙎‍♀️Portrait Avatars
      • Setup
        • Create a Portrait Avatar
        • Create a UI Portrait
      • Portrait Avatars
        • Scripting
      • Portrait3D
      • Portrait2D
      • Portrait UI
      • Avatar Camera
      • Important Considerations
    • 🎛️Audio Clip Combiner
    • 🌈Color Shifter
    • 🛠️Support Classes
      • Utilities.cs
      • InfinityExtensions.cs
  • ⌛Magic Time - Local Time Scale
    • Overview
    • ➡️Quick Start
    • 🛠️Integrations
    • 💡FAQ
    • Local Time Scale
      • Local Time Scale Scripting
    • Magic Time Manager
      • Magic Time Manager Scripting
    • Magic Time User
      • IHaveLocalTime
      • Magic Time User Scripting
      • Additional "Magic Time User" Components
    • Time Zone
  • Equipment Systems
    • Overview
    • Blend Shapes Manager
    • Blend Shapes Preset Manager
    • Prefab and Object Manager
      • Humanoid Demo & Setup
      • EquipmentObject.cs
      • Prefab Groups
      • Variables
      • Scripting Examples
    • Wardrobe Prefab Manager
  • 📽️General Tutorials
    • Quick 3rd Person Controller
  • ⚔️Legend of the Stones
    • Actors, Players, NPCs
    • Systems
      • Game State
  • External Links
  • Get them at the Asset Store
  • Connect on Discord
  • YouTube
  • Twitch
  • 🚧Work In Progress / Coming Soon
Powered by GitBook
On this page
  • Projectile Setup
  • Add a Collider
  • Add the Custom Script
  • Create a new Movement Behavior
  • Optional: Set the Simulation Speed of Particle Systems

Was this helpful?

  1. Projectile Factory
  2. Game Modules 4 Integration

Projectiles with TimeMod

PreviousGame Modules 4 IntegrationNextMagic Time for Projectile Factory

Last updated 8 months ago

Was this helpful?

The TimeMod class from enables global and local time scales to be used, meaning individual objects can have time scales unique to themselves while also being affected by a global time scale.

Projectiles can also make use of this class.

In the example below, I will demonstrate how to add a custom script to the projectiles which will track their unique TimeMod, and also set the Particle System simulation speed.

I will also demonstrate a new derived from an existing one which takes into account the GlobalTimeScale on the projecitles.

In the example below, I have a "TimeScaleZone" layer, which is used for areas on the map which may change the TimeScale of any object within it.

Projectile Setup

Add a Collider

First, add a collider to your projectile, and set the "Include" and "Exclude" layers so that only the TimeScaleZone is affected.

Note: Depending on your setup, you may need to create this logic in a new child object, so that there is only one collider on each object in your Projectile. If you don't have a collder, you can set this on the parent object.

Add the Custom Script

You'll want to create your own script, but you can copy this to start. You may have to change some values to align with the way you're setting up your global TimeMod object.

public class ProjectileTimeScale : MonoBehaviour
{
    public TimeMod timeMod = new TimeMod();
    public float LocalTimeScale => timeMod.TimeScale;
    public float GlobalTimeScale => timeMod.CombinedTimeScale(GameState.Instance.timeMod.TimeScale);
    public float DeltaTime => timeMod.UnscaledDeltaTime(GameState.Instance.timeMod.TimeScale);

    private float _lastTimeScale = 1f;
    
    public virtual void SetTimeScale(float timeScale)
    {
        _lastTimeScale = LocalTimeScale;
        timeMod.SetTimeScale(timeScale);
    }
    
    public virtual void ResetTimeScale() => SetTimeScale(_lastTimeScale);
    
    private void OnEnable()
    {
        _lastTimeScale = 1f;
        timeMod.SetTimeScale(1f);
    }
}

Create a new Movement Behavior

In this example, I'm going to create a new behavior that derives from MovementBehaviorForward, which comes with Projectile Factory. The same logic will apply to any movement behavior that moves the object via a deltaTime value.

Again, you can copy this, but you may need to modify things to better fit your project.

namespace MagicPigGames.ProjectileFactory
{
    [CreateAssetMenu(fileName = "New Basic Forward Movement Behavior Battle Ages",
        menuName = "Projectile Factory/Moving Behavior/Battle Ages - Basic Forward Movement Behavior")]
    [Serializable]
    public class MovementBehaviorForwardBattleAges : MovementBehaviorForward
    {
        private ProjectileTimeScale _projectileTimeScale;
        private ProjectileTimeScale ProjectileTimeScale
        {
            get
            {
                if (_isInitialized) return _projectileTimeScale; // Only check for this value once
                
                // Set the value with GetComponent
                if (_projectileTimeScale == null)
                    _projectileTimeScale = Projectile.GetComponent<ProjectileTimeScale>();
                
                // Set isInitialized to true and return the value
                _isInitialized = true;
                return _projectileTimeScale;
            }
        }
        
        private bool _isInitialized;
        
        protected override void Move()
        {
            var deltaTime = ProjectileTimeScale == null ? Time.deltaTime : ProjectileTimeScale.DeltaTime;
            Projectile.transform.Translate(LocalDirection * (ProjectileSpeed * deltaTime), Space.Self);
        }
    }
}

We compute the value of deltaTime in the Move() method, using the ProjectileTimeScale class if it's attached to the projectile, otherwise the standard Time.deltaTime.

Optional: Set the Simulation Speed of Particle Systems

You can create a new class which derives from ProjectileTimeScale to add additional methods, or create other classes that reference ProjectileTimeScale, whichever you prefer. Here we have a new child class called ProjectileParticleSystemTimeScale.

public class ProjectileParticleSystemTimeScale : MonoBehaviour
{
    public ProjectileTimeScale projectileTimeScale;
    public ParticleSystem[] particleSystems;

    private float _timeScale;

    public float TimeScale => projectileTimeScale.GlobalTimeScale;

    public void Update()
    {
        var timeScale = TimeScale;
        if (Mathf.Approximately(timeScale, _timeScale))
            return;
        
        _timeScale = timeScale;
        foreach (var ps in particleSystems)
            SetSimulationSpeed(ps, timeScale);
    }

    private void SetSimulationSpeed(ParticleSystem ps, float timeScale)
    {
        var main = ps.main;
        main.simulationSpeed = timeScale;
    }

    // Automatically populate particleSystems with all ParticleSystems in children
    public void OnValidate()
    {
        if (particleSystems == null || particleSystems.Length == 0)
            particleSystems = GetComponentsInChildren<ParticleSystem>();
        
        if (projectileTimeScale == null)
            projectileTimeScale = GetComponent<ProjectileTimeScale>();
    }
}

The OnValidate() method will automatically populate the list of Particle Systems. Set the list count to 0 to force the script to recompute the list if you add additional systems later.

You can use these scripts (and the collider) on other particles that aren't "Projectiles" as well, to ensure that muzzle flashes and impacts also react to the Time Scale.

🚀
Game Modules 4
Movement Behavior
Now this will only interact with the "TimeScaleZone" layer.