Personal Project, Unity, C#, Only Developer
Fallen Knight was a Third Year project developed using the Unity engine by a group of 9 people including myself. Tasked with making a functional game over the length of 4 releases and 22, 2 week sprints I helped create the game called Fallen Knight. Fallen knight is a first person action boss rush game with large inspiriations form the Dark souls games. During the course of development I had to wear alot of hats in order to meet the dead lines.

Tools Programmer

Created Debug manager to quickly execute parts of the bosses Ai for easy reiteration.

                        
//Initializion of debug buttons	 
    public void Init(string a_Name, DebugMenu a_DebugMenu, DebugButtonType a_DebugButtonType, Method a_Method)
    {
        m_Name = a_Name;
        m_ButtonText.text = a_Name;
        m_DebugMenu = a_DebugMenu;
        m_DebugbuttonType = a_DebugButtonType;
        m_Method = a_Method;
		
// Using a Lamdba mixed with a Delegate so when the button is clicked it will execute the method
        m_ReferenceToButton.onClick.AddListener(() => m_Method());
    } 
	
-----------------------------------------------------------------------------------------------------------------

	
//Setting A default debugging button
	
//Spawning the prefab of the button
	    DebugButton DebugButton = Instantiate(m_Prefab_DebugButton, m_MenuScreens[m_MenuScreens.Count - 1].gameObject.transform);
        DebugButton.gameObject.transform.localPosition = new Vector3(ScreenX, ScreenY + i * Offset, 0);
		
		
//Hooking up the method this button will call 
        DebugButton.Init("Immortality On", this, DebugButton.DebugButtonType.DebugMenutype, m_Player.SetImmortalityToTrue);
		
		
		
		
		
-----------------------------------------------------------------------------------------------------------------
		
//Attaching the different Toad AI Move List gotten from the list of Enums
		for (int i = 0; i < m_ToadAttackMoves.Length; i++)
        {
         ToadDebugButton toadbutton = Instantiate(m_Prefab_DebugToadButton, m_MenuScreens[m_MenuScreens.Count - 1].gameObject.transform);
         toadbutton.gameObject.transform.localPosition = new Vector3(ScreenX, ScreenY + i * Offset, 0);
         toadbutton.Init(i, m_ToadAttackMoves[i], m_ToadReference);
        }
        
                        
                    
                        
	 
Shader "OdellWaterShader" {
	Properties{
		_Color("Color", Color) = (1,1,1,1)
		_BlendColor("Blend Color", Color) = (1,1,1,1)
		_MainTex("Albedo (RGB)", 2D) = "white" {}
	_Glossiness("Smoothness", Range(0,1)) = 0.5
		_Metallic("Metallic", Range(0,1)) = 0.0
		_InvFade("Soft Factor", Range(0.01,3.0)) = 1.0
		_FadeLimit("Fade Limit", Range(0.00,1.0)) = 0.3
		_Scale("Scale", float) = 1
		_Speed("Speed", float) = 1
		_RipplePosition("Ripple Position",  Vector) = (0, 0, 0, 0)
		_WaterAlpha("WaterAlpha", float) = 0.9
		_Amplitude("RippleStrength", float) = 5
		_Wave("Wave", float) = 5
		_Frequency("Frequency", float) = 1
		_IsRippling("CanRipple", float) = 1
	}
		SubShader{
		Tags{ "Queue" = "Transparent" "RenderType" = "Transparent" }
		LOD 200

		CGPROGRAM
		// Physically based Standard lighting model, and enable shadows on all light types
#pragma surface surf Standard vertex:vert alpha:fade nolightmap

		// Use shader model 3.0 target, to get nicer looking lighting
#pragma target 3.0

		sampler2D _MainTex;

	struct Input {
		float2 uv_MainTex;
		float4 screenPos;
		float eyeDepth;
		float3 customValue;
	};

	half _Glossiness;
	half _Metallic;
	fixed4 _Color;
	fixed4 _BlendColor;
	float _Scale;
    float _Speed;
	float _Frequency;

	float _Amplitude;
	float _Wave;


	float _WaterAlpha;
	sampler2D_float _CameraDepthTexture;
	float4 _CameraDepthTexture_TexelSize;
	float4 _RipplePosition;
	float _FadeLimit;
	float _InvFade;

	float _IsRippling;

	void vert(inout appdata_full v, out Input o)
	{
		//NormalWave
		UNITY_INITIALIZE_OUTPUT(Input, o);
		COMPUTE_EYEDEPTH(o.eyeDepth);
		half offsetvert = ((v.vertex.x * v.vertex.x) + (v.vertex.z * v.vertex.z));
		half offsetvert2 = v.vertex.x + v.vertex.z;
		
// Calculating the waves time speed and frequency
		half value0 = _Scale * sin(_Time.w * _Speed * _Frequency + offsetvert2);


//Moving the vertex and normals to the new wave
		v.vertex.y += value0;
		v.normal.y += value0;
		o.customValue += value0;
		
	}

	void surf(Input IN, inout SurfaceOutputStandard o) {
// Albedo comes from a texture tinted by color
		fixed4 c = tex2D(_MainTex, IN.uv_MainTex) * _Color;
		o.Albedo = c.rgb;
// Metallic and smoothness come from slider variables
		o.Metallic = _Metallic;
		o.Smoothness = _Glossiness;


//Gets the camera depth buffer to calculate the rim
		float CameraDepth = SAMPLE_DEPTH_TEXTURE_PROJ(_CameraDepthTexture, UNITY_PROJ_COORD(IN.screenPos));
		float SceneDepth = LinearEyeDepth(CameraDepth);
		float partZ = IN.eyeDepth;

		float fade = 1.0;
		if (CameraDepth > 0.0) // Make sure the depth texture exists
//If the cameradepth is greater then create the rim
			fade = saturate(_InvFade * (SceneDepth - partZ));
		o.Alpha = c.a * fade; //(original line)
		
//Final Input
		o.Alpha = _WaterAlpha;
		
		if (fade < _FadeLimit)
		o.Albedo = c.rgb * fade + _BlendColor * (1 - fade);
	}
	ENDCG
	}
}
                        
                    

Grapics Programmer

As Graphics Programmer I created a Water shader and used depth buffer and vertex disfered rendering to create the shader.

Gameplay Programmer

As a Gameplay Programmer I created intricate boss Ai. The bosses were designed with a giant state machine of the actions they will execute and a complex web of when they would accomplish those actions.

                        
   public KingShieldCharge(AIController aAIController) : base(aAIController)
    {
        m_KingChargeTimer = Services.TimerManager.CreateTimer("m_KingChargeTimer", ChargeDuration, false);
        m_KingChargeDelayTimer = Services.TimerManager.CreateTimer("m_KingChargeDelayTimer", ChargeDelay, false);
    }


-----------------------------------------------------------------------------------------------------------------------


    public override void Start()
    {


        // Get the king's starting position
        m_PreMovePosition = ((AIKingController)m_AIController).transform.position;

        // Set hit and charging to false
        m_AlreadyHit = false;
        m_Charging = false;

        // Setup the timers
        m_KingChargeDelayTimer.Restart();

        // Start the animation
        ((AIKingController)m_AIController).m_Animator.SetTrigger("Charge");

    }

--------------------------------------------------------------------------------------------------------------------------

// Update is called once per frame
    public override void Update()
    {
// If the delay timer is running
        if(m_KingChargeDelayTimer.IsRunning() == true)
        {
// Turn to look at the player
            ((AIKingController)m_AIController).TurnToPlayer();
        }

// If the delay is done and the king isin't charging
        if (m_KingChargeDelayTimer.IsFinished() && m_Charging == false)
        {
// Set charging to true and start the charge timer
            m_Charging = true;
            m_KingChargeTimer.Restart();

// Sets the target's position to the Player's position and 
            m_TargetPosition = ((AIKingController)m_AIController).transform.position + (((AIKingController)m_AIController).transform.forward * (((AIKingController)m_AIController).GetDistanceToPlayer() + m_ChargeDistanceBehindPlayer));
        }

// If the king is charging
        if (m_KingChargeTimer.IsRunning() && m_Charging == true)
        {
// CHARGE!!!!!!
            ((AIKingController)m_AIController).transform.position = Vector3.Lerp(m_PreMovePosition, m_TargetPosition, m_KingChargeTimer.GetPercentage());
        }

// If the king is done charging
        if (m_KingChargeTimer.IsFinished() && m_Charging == true)
        {
 // If the animation is done
            if (((AIKingController)m_AIController).m_Animator.GetCurrentAnimatorStateInfo(0).IsTag("ShieldEnd") && ((AIKingController)m_AIController).m_Animator.GetCurrentAnimatorStateInfo(0).normalizedTime >= 0.98f || ((AIKingController)m_AIController).m_Animator.GetCurrentAnimatorStateInfo(0).normalizedTime >= 1.0f)
            {
// Attack is finished
                ((AIKingController)m_AIController).CurrentActionFinished();
            }
        }

// If the king is charging, hit the player and hasn't already hit the player
        if (m_Charging == true && ((AIKingController)m_AIController).m_KingChargeTrigger.m_IsPlayerinside == true && m_AlreadyHit == false)
        {
// Set hit to true
            m_AlreadyHit = true;

 // Deal Damage to player
            Services.GameManager.Player.TakeDamage(Constants.KingSheildChargeDamage);

// Set the force and radius
            float Force = 100;

// Push the player away
            Services.GameManager.Player.MovementController.PushPlayer(((AIKingController)m_AIController).transform.position, Force);
        }
    }
}
    
                        
                    

Fallen Knight was a great project to work on that helped me grow as a programmer and as a person. Communicating with a large group of people with hierarchy was a challenge but in the end we persisted and created a great work that we can all be proud of.

Gallery