AI FSM changes.

- Protoyped on the AI movement, found solutions for turns and
   moving after impacting the player.
- Created a full base for AI state machine.
- Worked on binding the core AI logic with the finite state machine.
This commit is contained in:
Ashby Issac 2026-01-07 19:38:03 +05:30
parent 90172daae5
commit c466e28d6c
31 changed files with 1977 additions and 65 deletions

View File

@ -22,4 +22,4 @@ MonoBehaviour:
rotationSpeed: 2 rotationSpeed: 2
tireRotationAngle: 20 tireRotationAngle: 20
speedValue: 50 speedValue: 50
accelSpeed: 50 accelSpeed: 100

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 2190dc59a173e463f81234566cee14be
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: ccc494c7b34894ebdb6ab672fa47804d
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 23800000
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 36d3513c3c72245678185ccd17a13c64
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,163 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class AICarController : MonoBehaviour, ICar
{
#region Fields
private float speed;
private float speedMax = 35f;
private float speedMin = -25f;
private float acceleration = 10f;
private float brakeSpeed = 50f;
private float reverseSpeed = 15f;
private float idleSlowdown = 5f;
private float turnSpeed;
private float turnSpeedMax = 150f;
private float turnSpeedAcceleration = 150f;
private float turnIdleSlowdown = 250f;
private float forwardAmount;
private float turnAmount;
private Rigidbody carRigidbody;
public GameplayManager GameplayManager
{
get;
private set;
}
#endregion
private void Awake()
{
carRigidbody = GetComponent<Rigidbody>();
}
public void Init(GameplayManager gameplayManager)
{
this.GameplayManager = gameplayManager;
}
private void Update()
{
CalculateAccelaration();
if (speed < 0)
{
// Going backwards, invert wheels
// turnAmount = turnAmount * -1f;
}
if (turnAmount > 0 || turnAmount < 0)
{
// Turning
if ((turnSpeed > 0 && turnAmount < 0) || (turnSpeed < 0 && turnAmount > 0))
{
// Changing turn direction
float minTurnAmount = 20f;
turnSpeed = turnAmount * minTurnAmount;
}
turnSpeed += turnAmount * turnSpeedAcceleration * Time.deltaTime;
}
else
{
// Not turning
if (turnSpeed > 0)
{
turnSpeed -= turnIdleSlowdown * Time.deltaTime;
}
if (turnSpeed < 0)
{
turnSpeed += turnIdleSlowdown * Time.deltaTime;
}
if (turnSpeed > -1f && turnSpeed < +1f) {
// Stop rotating
turnSpeed = 0f;
}
}
float speedNormalized = speed / speedMax;
float invertSpeedNormalized = Mathf.Clamp(1 - speedNormalized, .75f, 1f);
turnSpeed = Mathf.Clamp(turnSpeed, -turnSpeedMax, turnSpeedMax);
carRigidbody.angularVelocity = new Vector3(0, turnSpeed * (invertSpeedNormalized * 1f) * Mathf.Deg2Rad, 0);
if (transform.eulerAngles.x > 2 || transform.eulerAngles.x < -2 || transform.eulerAngles.z > 2 || transform.eulerAngles.z < -2)
{
transform.eulerAngles = new Vector3(0, transform.eulerAngles.y, 0);
}
}
private void CalculateAccelaration()
{
if (forwardAmount > 0)
{
// Accelerating
speed += acceleration * Time.deltaTime;
}
else if (forwardAmount < 0)
{
if (speed > 0)
{
// Braking
speed += forwardAmount * brakeSpeed * Time.deltaTime;
}
else
{
// Reversing
speed += forwardAmount * reverseSpeed * Time.deltaTime;
}
}
else
{
// Not accelerating or braking
if (speed > 0)
{
speed -= idleSlowdown * Time.deltaTime;
}
if (speed < 0)
{
speed += idleSlowdown * Time.deltaTime;
}
}
speed = Mathf.Clamp(speed, speedMin, speedMax);
carRigidbody.velocity = transform.forward * speed;
}
public void SetInputs(float forwardAmount, float turnAmount) {
this.forwardAmount = forwardAmount;
this.turnAmount = turnAmount;
}
public void ClearTurnSpeed() {
turnSpeed = 0f;
}
public float GetSpeed() {
return speed;
}
public void SetSpeedMax(float speedMax) {
this.speedMax = speedMax;
}
public void SetTurnSpeedMax(float turnSpeedMax) {
this.turnSpeedMax = turnSpeedMax;
}
public void SetTurnSpeedAcceleration(float turnSpeedAcceleration) {
this.turnSpeedAcceleration = turnSpeedAcceleration;
}
public void StopCompletely() {
speed = 0f;
turnSpeed = 0f;
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0fca7c6ea6b2be241844f325ebfca4c7
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,142 @@
using System;
using DG.Tweening;
using Unity.VisualScripting;
using UnityEditor.Callbacks;
using UnityEngine;
public class AICarDriver : MonoBehaviour
{
[SerializeField] private Transform targetPositionTranform;
private AICarController carDriver;
private Vector3 targetPosition;
private void Awake()
{
carDriver = GetComponent<AICarController>();
impactTimer = new TimerSystem();
// SetImpactTimer();
}
private TimerSystem impactTimer;
private float forwardAmount = 0f;
private float turnAmount = 0f;
public void UpdateMovement(Action onComplete = null)
{
// provide a roamPoint
SetTargetPosition(targetPositionTranform.position);
float targetDistReach = 2f;
float distanceToTarget = Vector3.Distance(transform.position, targetPosition);
Debug.Log($"distanceToTarget :: {distanceToTarget}");
if (distanceToTarget > targetDistReach)
{
// Still too far, keep going
Vector3 dirToMovePosition = (targetPosition - transform.position).normalized;
float dot = Vector3.Dot(transform.forward, dirToMovePosition);
if (dot > 0)
{
// Target in front
forwardAmount = 1f;
float stoppingDistance = 2f;
float stoppingSpeed = 5f;
// if (onImpact)
// {
// the target location should be set to next roam point or to another enemy/player
// and then DoReverse()
// DoReverse();
// }
// else if (canCheck)
// {
if (distanceToTarget < stoppingDistance && carDriver.GetSpeed() > stoppingSpeed)
{
// Within stopping distance and moving forward too fast
forwardAmount = -1f;
}
// }
// after impact reverse for about 0.5 seconds
}
else
{
// Target behind
float reverseDistance = 25f;
if (distanceToTarget > reverseDistance)
{
// Too far to reverse
forwardAmount = 1f;
// if (onImpact)
// {
// the target location should be set to next roam point or to another enemy/player
// and then DoReverse()
// DoReverse();
// }
}
else
{
forwardAmount = -1f;
// Check if DoReverse can be called instead
}
}
turnAmount = FindTurnAmt();
}
else
{
// Reached target
Debug.Log($"Target reached: {forwardAmount}");
if (forwardAmount == 1)
onComplete?.Invoke();
forwardAmount = carDriver.GetSpeed() > 15f ? -1f : 0f;
turnAmount = 0f;
}
carDriver.SetInputs(forwardAmount, turnAmount);
}
public void DoReverse(Action onComplete)
{
// TODO :: Set target position before doing reverse
Debug.Log($"CarDriverAI :: onImpact");
if (impactTimer.IsTimerComplete)
{
impactTimer.Init(0.5f, onComplete: () =>
{
Debug.Log($"ImpactTimer :: OnTimerComplete");
forwardAmount = 1f;
turnAmount = FindTurnAmt();
carDriver.SetInputs(forwardAmount, turnAmount);
onComplete?.Invoke();
});
}
impactTimer.UpdateTimer(Time.deltaTime);
forwardAmount = -1f;
turnAmount = FindTurnAmt();
carDriver.SetInputs(forwardAmount, turnAmount);
}
private float FindTurnAmt()
{
Vector3 dirToMovePosition = (targetPosition - transform.position).normalized;
float angleToDir = Vector3.SignedAngle(transform.forward, dirToMovePosition, Vector3.up);
return angleToDir > 0 ? 1f : -1f;
}
public void SetTargetPosition(Vector3 targetPosition)
{
this.targetPosition = targetPosition;
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: eb59b9c1ad3c8e34999f1b2e07b5774f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,5 @@
public interface ICar
{
void Init(GameplayManager gameplayManager);
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 2a269c48eac634e32be15927f5f67a83
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,19 +0,0 @@
using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;
public class AIController : MonoBehaviour
{
private BaseState currentState;
private void Start()
{
currentState = new IdleState();
}
private void Update()
{
currentState = currentState.ProcessStates();
}
}

View File

@ -0,0 +1,25 @@
using System;
using UnityEngine;
public class AIStateProcesser : MonoBehaviour
{
private BaseState currentState;
private AICarDriver carDriverAI;
private AICarController aiCarController;
private void Awake()
{
carDriverAI = GetComponent<AICarDriver>();
aiCarController = GetComponent<AICarController>();
}
private void Start()
{
currentState = new IdleState(carDriverAI, aiCarController.GameplayManager);
}
private void Update()
{
currentState = currentState.ProcessStates();
}
}

View File

@ -2,7 +2,7 @@ using UnityEngine;
public class AcquireTargetState : BaseState public class AcquireTargetState : BaseState
{ {
public AcquireTargetState() : base() public AcquireTargetState(AICarDriver aiCarDriver, GameplayManager gameplayManager) : base(aiCarDriver, gameplayManager)
{ {
Debug.Log($"### {this} constructor"); Debug.Log($"### {this} constructor");
} }
@ -19,6 +19,14 @@ public class AcquireTargetState : BaseState
base.Update(); base.Update();
Debug.Log($"### {this} Update STAGE"); Debug.Log($"### {this} Update STAGE");
// while it's roaming check for targets
// Find the target and once the target is found then charge toward that specific target
if (HasFoundTarget())
{
base.Exit();
nextState = new ChargeState(aiCarDriver, gameplayManager);
}
} }
protected override void Exit() protected override void Exit()
@ -27,4 +35,10 @@ public class AcquireTargetState : BaseState
Debug.Log($"### {this} Exit STAGE"); Debug.Log($"### {this} Exit STAGE");
} }
public bool HasFoundTarget()
{
return false;
}
} }

View File

@ -1,12 +1,20 @@
using UnityEngine;
public class BaseState public class BaseState
{ {
protected STAGE stage; protected STAGE stage;
protected BaseState nextState; protected BaseState nextState;
protected Transform currentTarget;
protected AICarDriver aiCarDriver;
protected GameplayManager gameplayManager;
public BaseState() public BaseState(AICarDriver aiCarDriver, GameplayManager gameplayManager)
{ {
stage = STAGE.Enter; stage = STAGE.Enter;
this.aiCarDriver = aiCarDriver;
this.gameplayManager = gameplayManager;
} }
protected virtual void Enter() => stage = STAGE.Update; protected virtual void Enter() => stage = STAGE.Update;

View File

@ -2,7 +2,7 @@ using UnityEngine;
public class ChargeState : BaseState public class ChargeState : BaseState
{ {
public ChargeState() : base() public ChargeState(AICarDriver aiCarDriver, GameplayManager gameplayManager) : base(aiCarDriver, gameplayManager)
{ {
Debug.Log($"### {this} constructor"); Debug.Log($"### {this} constructor");
} }
@ -12,6 +12,7 @@ public class ChargeState : BaseState
base.Enter(); base.Enter();
Debug.Log($"### {this} Enter STAGE"); Debug.Log($"### {this} Enter STAGE");
// update the values for charging
} }
protected override void Update() protected override void Update()
@ -19,6 +20,11 @@ public class ChargeState : BaseState
base.Update(); base.Update();
Debug.Log($"### {this} Update STAGE"); Debug.Log($"### {this} Update STAGE");
aiCarDriver.UpdateMovement(() =>
{
base.Exit();
nextState = new ImpactState(aiCarDriver, gameplayManager);
});
} }
protected override void Exit() protected override void Exit()

View File

@ -3,7 +3,7 @@ using UnityEngine;
public class IdleState : BaseState public class IdleState : BaseState
{ {
public IdleState() : base() public IdleState(AICarDriver aiCarDriver, GameplayManager gameplayManager) : base(aiCarDriver, gameplayManager)
{ {
Debug.Log($"### {this} constructor"); Debug.Log($"### {this} constructor");
} }
@ -20,7 +20,9 @@ public class IdleState : BaseState
base.Update(); base.Update();
// use a mod timer system and when timer completes then move onto the next state (RoamState) // use a mod timer system and when timer completes then move onto the next state (RoamState)
nextState = new RoamState(); base.Exit();
nextState = new AcquireTargetState(aiCarDriver, gameplayManager);
Debug.Log($"### {this} Update STAGE"); Debug.Log($"### {this} Update STAGE");
} }

View File

@ -2,7 +2,7 @@ using UnityEngine;
public class ImpactState : BaseState public class ImpactState : BaseState
{ {
public ImpactState() : base() public ImpactState(AICarDriver aiCarDriver, GameplayManager gameplayManager) : base(aiCarDriver, gameplayManager)
{ {
Debug.Log($"### {this} constructor"); Debug.Log($"### {this} constructor");
} }
@ -19,6 +19,10 @@ public class ImpactState : BaseState
base.Update(); base.Update();
Debug.Log($"### {this} Update STAGE"); Debug.Log($"### {this} Update STAGE");
// do actions when an impact happens
base.Exit();
nextState = new RecoverState(aiCarDriver, gameplayManager);
} }
protected override void Exit() protected override void Exit()

View File

@ -2,7 +2,7 @@ using UnityEngine;
public class RecoverState : BaseState public class RecoverState : BaseState
{ {
public RecoverState() : base() public RecoverState(AICarDriver aiCarDriver, GameplayManager gameplayManager) : base(aiCarDriver, gameplayManager)
{ {
Debug.Log($"### {this} constructor"); Debug.Log($"### {this} constructor");
} }
@ -19,6 +19,11 @@ public class RecoverState : BaseState
base.Update(); base.Update();
Debug.Log($"### {this} Update STAGE"); Debug.Log($"### {this} Update STAGE");
aiCarDriver.DoReverse(() =>
{
base.Exit();
nextState = new RoamState(aiCarDriver, gameplayManager);
});
} }
protected override void Exit() protected override void Exit()

View File

@ -2,7 +2,13 @@ using UnityEngine;
public class RoamState : BaseState public class RoamState : BaseState
{ {
public RoamState() : base() private bool hasCompletedRoaming = false;
private float roamDuration = 2f;
private Vector3 currentRoamingPoint = Vector3.zero;
private TimerSystem roamTimerSystem = null;
public RoamState(AICarDriver aiCarDriver, GameplayManager gameplayManager) : base(aiCarDriver, gameplayManager)
{ {
Debug.Log($"### {this} constructor"); Debug.Log($"### {this} constructor");
} }
@ -14,20 +20,39 @@ public class RoamState : BaseState
Debug.Log($"### {this} Enter STAGE"); Debug.Log($"### {this} Enter STAGE");
// get the target point // get the target point
currentRoamingPoint = gameplayManager.GetRoamingPoint();
aiCarDriver.SetTargetPosition(currentRoamingPoint);
roamTimerSystem = new TimerSystem();
hasCompletedRoaming = false;
roamTimerSystem.Init(roamDuration, onComplete: () => hasCompletedRoaming = true);
} }
protected override void Update() protected override void Update()
{ {
base.Update(); base.Update();
// keeping roaming for a specific duration // keep roaming for a specific duration
// use a set of target points which would be placed on the arena, // use a set of target points which would be placed on the arena,
// get one of the target point and then start roaming towards that point. // get one of the target point and then start roaming towards that point.
// if an enemy/player is found within a specific radius and in front of- // if an enemy/player is found within a specific radius and in front of-
// -the player then go to the next state after acquiring the target- // -the AI then go to the next state after acquiring the target-
// -(next state could be ChargeState) // -(next state could be ChargeState)
// Set Target location
if (!hasCompletedRoaming)
{
roamTimerSystem.UpdateTimer(Time.deltaTime);
aiCarDriver.UpdateMovement();
}
else
{
base.Exit();
nextState = new AcquireTargetState(aiCarDriver, gameplayManager);
}
Debug.Log($"### {this} Update STAGE"); Debug.Log($"### {this} Update STAGE");
} }

View File

@ -4,10 +4,8 @@ using UnityEngine;
using System.Collections; using System.Collections;
using System.ComponentModel; using System.ComponentModel;
using UnityEngine.SceneManagement; using UnityEngine.SceneManagement;
using UnityEngine.EventSystems;
using Newtonsoft.Json;
public class CarController : MonoBehaviour public class PlayerCarController : MonoBehaviour, ICar
{ {
[SerializeField] private bool isDebugTest = false; [SerializeField] private bool isDebugTest = false;
@ -17,7 +15,7 @@ public class CarController : MonoBehaviour
[SerializeField] private Rigidbody carRigidbody; [SerializeField] private Rigidbody carRigidbody;
[SerializeField] private CarSpecs carSpecs; [SerializeField] private PlayerCarSpecs carSpecs;
[SerializeField] private Vector3 customCenterOfMass; [SerializeField] private Vector3 customCenterOfMass;
[SerializeField] private AnimationCurve steerLeftAnimCurve; [SerializeField] private AnimationCurve steerLeftAnimCurve;
[SerializeField] private AnimationCurve steerRightAnimCurve; [SerializeField] private AnimationCurve steerRightAnimCurve;
@ -33,7 +31,7 @@ public class CarController : MonoBehaviour
private float tiresInGround = 0f; private float tiresInGround = 0f;
[Category("Script-Object-Refs.")] [Category("Script-Object-Refs.")]
private CarSystem carSystem; private PlayerCarSystem carSystem;
private TimerSystem timerSystem; private TimerSystem timerSystem;
[Category("Tags.")] [Category("Tags.")]
@ -50,14 +48,22 @@ public class CarController : MonoBehaviour
public Action<float> OnCarRotate; public Action<float> OnCarRotate;
public Action<string> OnGameOver; public Action<string> OnGameOver;
public void Init() public GameplayManager GameplayManager
{ {
get;
private set;
}
public void Init(GameplayManager gameplayManager)
{
this.GameplayManager = gameplayManager;
isGameOver = false; isGameOver = false;
tiresCount = tireTransforms.Length; tiresCount = tireTransforms.Length;
timerSystem = new TimerSystem(); timerSystem = new TimerSystem();
remTime = timerSystem.Timer; // remTime = timerSystem.Timer;
carSystem = new CarSystem(this, carRigidbody, carSpecs, frontTireTransforms, steerLeftAnimCurve: steerLeftAnimCurve, steerRightAnimCurve: steerRightAnimCurve, accelAnimCurve: accelAnimCurve); carSystem = new PlayerCarSystem(this, carRigidbody, carSpecs, frontTireTransforms, steerLeftAnimCurve: steerLeftAnimCurve, steerRightAnimCurve: steerRightAnimCurve, accelAnimCurve: accelAnimCurve);
} }
private void EnableGameOverState() private void EnableGameOverState()

View File

@ -3,7 +3,7 @@ using System.Collections.Generic;
using UnityEngine; using UnityEngine;
[CreateAssetMenu(fileName = "CarSpecs", menuName = "CarSpecs", order = 1)] [CreateAssetMenu(fileName = "CarSpecs", menuName = "CarSpecs", order = 1)]
public class CarSpecs : ScriptableObject public class PlayerCarSpecs : ScriptableObject
{ {
public float dampingForce = 50; public float dampingForce = 50;
public float strength = 500; public float strength = 500;

View File

@ -3,10 +3,10 @@ using System.Collections.Generic;
using System.ComponentModel; using System.ComponentModel;
using UnityEngine; using UnityEngine;
public class CarSystem : ICarComponents public class PlayerCarSystem : ICarComponents
{ {
[Category("Global Attributes")] private Rigidbody carRigidbody; [Category("Global Attributes")] private Rigidbody carRigidbody;
private CarSpecs carSpecs; private PlayerCarSpecs carSpecs;
[Category("Animation Curves")] private AnimationCurve steerLeftAnimCurve; [Category("Animation Curves")] private AnimationCurve steerLeftAnimCurve;
[Category("Animation Curves")] private AnimationCurve steerRightAnimCurve; [Category("Animation Curves")] private AnimationCurve steerRightAnimCurve;
@ -29,9 +29,9 @@ public class CarSystem : ICarComponents
private Vector3 accelForce; private Vector3 accelForce;
private Transform[] frontTireTransforms; private Transform[] frontTireTransforms;
private CarController gameplayControllerInst; private PlayerCarController gameplayControllerInst;
public CarSystem(CarController gameplayController, Rigidbody carRigidbody = null, CarSpecs carSpecs = null, Transform[] frontTireTransforms = null, public PlayerCarSystem(PlayerCarController gameplayController, Rigidbody carRigidbody = null, PlayerCarSpecs carSpecs = null, Transform[] frontTireTransforms = null,
AnimationCurve steerLeftAnimCurve = null, AnimationCurve steerRightAnimCurve = null, AnimationCurve accelAnimCurve = null) AnimationCurve steerLeftAnimCurve = null, AnimationCurve steerRightAnimCurve = null, AnimationCurve accelAnimCurve = null)
{ {
gameplayControllerInst = gameplayController; gameplayControllerInst = gameplayController;

View File

@ -1,12 +1,17 @@
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using UnityEngine; using UnityEngine;
public class GameplayManager : MonoBehaviour, IBase, IBootLoader, IDataLoader public class GameplayManager : MonoBehaviour, IBase, IBootLoader, IDataLoader
{ {
[SerializeField] private CarController carController; [SerializeField] private GameObject[] allCarsInScene; // contains enemy cars and player car
[]
[SerializeField] private PlayerCarController playerCarController; // TODO :: initialize roamPoints here
public CarController CarController => carController; [SerializeField] private List<Transform> roamPoints; // TODO :: initialize roamPoints here
public PlayerCarController CarController => playerCarController;
public void Initialize() public void Initialize()
{ {
@ -15,6 +20,21 @@ public class GameplayManager : MonoBehaviour, IBase, IBootLoader, IDataLoader
public void InitializeData() public void InitializeData()
{ {
carController.Init(); foreach (var car in allCarsInScene)
{
car.GetComponent<ICar>().Init(this);
}
}
public Vector3 GetRoamingPoint()
{
var randomIndex = Random.Range(0, roamPoints.Count);
return roamPoints[randomIndex].position;
}
public Transform GetTargetToAttack()
{
var randomIdx = Random.Range(0, allCarsInScene.Length);
return allCarsInScene[randomIdx].transform;
} }
} }

View File

@ -1,29 +1,50 @@
using System;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using UnityEngine; using UnityEngine;
public class TimerSystem public class TimerSystem
{ {
private float timer = 10f; private float timeRem;
private float timerIncrement = 5f; private float maxTimeAvail;
public float Timer => timer; private Action onTimerComplete = null;
private Action onTimerInProgress = null;
public float TimerIncrement = 5f; public bool IsTimerComplete
public TimerSystem()
{ {
CarController.OnCheckpointReached += UpdateTimer; get;
private set;
} }
private void IncreaseTimer() public bool IsInitialized
{ {
timer += timerIncrement; get;
private set;
} }
public void UpdateTimer(float remTime) public void Init(float maxTimeAvail, Action onComplete = null, Action inProgress = null, Action onStart = null)
{ {
timer = remTime; timeRem = 0;
IncreaseTimer(); IsTimerComplete = false;
IsInitialized = true;
this.maxTimeAvail = maxTimeAvail;
this.onTimerComplete = onComplete;
this.onTimerInProgress = inProgress;
}
public void UpdateTimer(float deltaTime)
{
if (timeRem < maxTimeAvail)
{
timeRem += deltaTime;
onTimerInProgress?.Invoke();
}
else
{
timeRem = 0;
onTimerComplete?.Invoke();
IsTimerComplete = true;
}
} }
} }

View File

@ -69,7 +69,7 @@ NavMeshProjectSettings:
cost: 1 cost: 1
- name: - name:
cost: 1 cost: 1
m_LastAgentTypeID: -887442657 m_LastAgentTypeID: -1372625422
m_Settings: m_Settings:
- serializedVersion: 2 - serializedVersion: 2
agentTypeID: 0 agentTypeID: 0
@ -85,7 +85,28 @@ NavMeshProjectSettings:
manualTileSize: 0 manualTileSize: 0
tileSize: 256 tileSize: 256
accuratePlacement: 0 accuratePlacement: 0
maxJobWorkers: 0
preserveTilesOutsideBounds: 0
debug:
m_Flags: 0
- serializedVersion: 2
agentTypeID: -1372625422
agentRadius: 0.5
agentHeight: 1.2
agentSlope: 45
agentClimb: 0.4
ledgeDropHeight: 0
maxJumpAcrossDistance: 0
minRegionArea: 2
manualCellSize: 0
cellSize: 0.16666667
manualTileSize: 0
tileSize: 256
accuratePlacement: 0
maxJobWorkers: 0
preserveTilesOutsideBounds: 0
debug: debug:
m_Flags: 0 m_Flags: 0
m_SettingNames: m_SettingNames:
- Humanoid - Humanoid
- New Agent