Project Description

Published On: February 13th, 20230 Comments

The game pictured in Projectile Arcing in Unity with Animation Curves, this prototype was the result of wanting to try out and learn some Unity Programming Patterns after my first full semester in AAU’s Game Design MA program.

The object of the game is to build the enemy path in order to create the most optimized killbox(es); however, the path has a chance to branch after the player’s tile laying phase ends, throwing a monkey wrench in the player’s carefully planned route. Similar to Isle of Arrows (whose beta came out about a month or so into me working on this project), the idea is to eventually give the player enemy path tiles with further attributes that will automatically Slow/Poison/Stun/etc. any enemy who steps on them.

If I ever return to this project, the next hurdle is figuring out the enemy wave progression.

Programming Notes

using System;
using UnityEngine;

[CreateAssetMenu (fileName = "UnlockCondition_", menuName = "Scriptable Objects/Tech Tree/Unlock Condition", order = 52)]
public class UnlockCondition : ScriptableObject, ISerializationCallbackReceiver
{
#if UNITY_EDITOR
    [TextArea] public string developerDescription = "";
#endif
    public string DisplayName;
    public EventObject ConditionEvent;
    public EventObjectInt ConditionIntEvent;
    public EventObjectGameObject ConditionGameObjectEvent;
    
    public ConditionFilter ConditionFilter;
    public int ConditionGoal;
    
    [SerializeField] private int ConditionCountDefault;
    [NonSerialized] public int ConditionCount;
    
    [SerializeField] private bool ConditionMetDefault;
    [NonSerialized] public bool ConditionMet;

    #region Event Suubscriptions
    private void OnEnable()
    {
        if(ConditionEvent) ConditionEvent.RegisterListener(OnConditionEvent);
        if(ConditionGameObjectEvent) ConditionGameObjectEvent.RegisterListener(OnConditionGameObjectEvent);
        if(ConditionIntEvent) ConditionIntEvent.RegisterListener(OnConditionIntEvent);
    }

    private void OnDisable()
    {
        if(ConditionGameObjectEvent) ConditionGameObjectEvent.UnregisterListener(OnConditionGameObjectEvent);
    }
    #endregion

    public void OnBeforeSerialize() { }
    // reset count and bool after each play session
    public void OnAfterDeserialize()
    {
        ConditionCount = ConditionCountDefault;
        ConditionMet = ConditionMetDefault;
    }


    protected virtual void OnConditionEvent()
    {
        // don't bother if we already met our condition
        if (ConditionMet) return;
        
        // increase our count and check if we're done
        ConditionCount++;
        CheckCondition();
        Debug.Log(name + " condition " + ConditionCount + " of " + ConditionGoal);
    }

    protected virtual void OnConditionIntEvent(int conditionInt)
    {
        // don't bother if we already met our condition
        if (ConditionMet) return;
        
        // don't fire on zero parameter
        if (conditionInt == 0) return;
        
        // increase our count and check if we're done
        ConditionCount+= conditionInt;
        CheckCondition();
        Debug.Log(name + " condition " + ConditionCount + " of " + ConditionGoal);
    }

    protected virtual void OnConditionGameObjectEvent(GameObject conditionObject)
    {
        // don't bother if we already met our condition
        if (ConditionMet) return;
        
        // don't fire on null parameter
        if (!conditionObject) return;

        // if we have a filter, make sure we match it before continuing
        if (ConditionFilter!=null)
        {
            if (!ConditionFilter.CheckFilter(conditionObject)) return;
        }

        // increase our count and check if we're done
        ConditionCount++;
        CheckCondition();
        Debug.Log(name + " condition " + ConditionCount + " of " + ConditionGoal);
    }

    protected void CheckCondition()
    {
        if (ConditionCount < ConditionGoal) return;
        
        ConditionMet = true;
    }

}

  • The setup for an actual TechTreeUnlock is simple:
using System.Collections.Generic;
using System.Linq;
using UnityEngine;

[CreateAssetMenu (fileName = "TechUnlock_", menuName = "Scriptable Objects/Tech Unlock", order = 51)]
public class TechUnlock : ScriptableObject
{
    public string Name;
    public List<UnlockCondition> UnlockConditions;
    public List<BuildableObject> Unlocks;
    public List<BuildableObject> Hides;
    public bool Unlocked => UnlockConditions.All(condition => condition.ConditionMet);
}


  • The Inspector setup for unlocking Kinetic Weapons II after building 10 Kinetic Towers (Hides can be used if the new building unlocked replaces an existing Buildable):

Download/Play

Project Details

Skills Needed:

Categories:

By:

Project Images

Random Survival
Ron Swansong

Leave a Reply

Share This: