Assemblies Made and Refactored Code Folders

Created assemblies for the new design code. Relocated legacy scripts into a legacy folder and made a "new_design" folder for new design.
This commit is contained in:
MarcoHampel
2023-09-11 19:39:27 -04:00
parent 84b455b473
commit f8590432ba
209 changed files with 729 additions and 0 deletions

View File

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

View File

@ -0,0 +1,39 @@
using UnityEngine;
using System;
/*
# Enemy System
## States
1. **Passive**
- Enemy is unaware of danger and performing idle actions. Not actively searching for anything.
- Perception range is at its minimum.
- If agressive target is "visible" enter `Agressive` state.
- If nonagressive target is "visible" enter `Aware` state.
2. **Guard**
- Enemy is looking out for danger. Can be moving along a path or standing
- Perception range is at regular level.
- If aggressive target is "visible" enter `Agressive` state.
- If nonagressive target is "visible" enter `Aware` state.
3. **Aware**
- Enemy has noticed something and is moving towards location of interest.
- Peception range is at regular level.
- If player is "visible" enter `Agressive` state.
- If nonagresive target is "visible" of equal or greater importance change target.
- If at location and no new item of note is added to "visible", then enter either `Passive` or `Guard` mode based on original mode.
4. **Aggressive**
- Enemy has noticed player:
- Apply these actions in sequence:
a. If player has not been "visible" for more than 5 seconds enter `Guard` mode.
b. If player has not been "visible" for < 5 seconds move to last location it was visible.
c. If player is in attack range and is visible, stop moving, and attack if able.
d. If player is not in attack range and is visible, run in direction of player.
*/
class AIStateMachine : MonoBehaviour{
[SerializeField]
private EnemyAI.EnemyState state;
}

View File

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

View File

@ -0,0 +1,12 @@
using System;
namespace EnemyAI{
///The state the enemy is currently in.
///Passive: Enemy is not searching for anyone and is at minimum perception distance.
///Guard: Enemy is on the lookout for enemies. May be following a patrol path.
///Aware: Enemy has noticed something and is investigating it.
///Aggressive: Enemy has seen something it wants to attack and is performing its attack.
public enum EnemyState{PASSIVE, GUARD, AWARE, AGGRESSIVE};
}

View File

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

View File

@ -0,0 +1,134 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Enemy {
public class SkinlessMonsterAnimator : MonoBehaviour
{
[SerializeField] private Animator animator;
[SerializeField]
[Tooltip("This is the object with the skin dissolve material")]
private GameObject modelObject;
[SerializeField] private List<GameObject> objectsThatFallOnDeath = new();
[SerializeField] private float deathSpeed = 5f;
[SerializeField] private float fastDeathduration = 1f;
[SerializeField] private float deathDuration = 5f;
private float curDeathSpeed = 5f;
private Material dissolveMaterial;
private bool isAlive = true;
private float speed;
public bool IsRunning { get; private set; }
// Start is called before the first frame update
private void Start()
{
dissolveMaterial = modelObject.GetComponent<SkinnedMeshRenderer>().materials[0];
curDeathSpeed = deathSpeed;
}
// Update is called once per frame
private void Update()
{
if (isAlive)
{
animator.SetFloat("Speed", speed);
}
else
{
var quantity = dissolveMaterial.GetFloat("_DissolveQuantity");
quantity = Mathf.Lerp(quantity, -2, Time.deltaTime * curDeathSpeed);
dissolveMaterial.SetFloat("_DissolveQuantity", quantity);
}
}
public void StartMoving()
{
if (isAlive)
{
IsRunning = true;
speed = 1;
}
}
public void StopMoving()
{
if (isAlive)
{
speed = 0;
IsRunning = false;
}
}
public void Attack()
{
if (isAlive) animator.SetTrigger("Attack");
}
/// <summary>
/// 0,1,2,3
/// </summary>
/// <param name="attackType"></param>
public void SetAttackType(int attackType)
{
animator.SetInteger("AttackIndex", attackType);
}
public void InLight()
{
if (isAlive)
animator.SetBool("InLight", true);
}
public void NotInLight()
{
if (isAlive)
animator.SetBool("InLight", false);
}
public void AttackScream()
{
if (isAlive)
animator.SetTrigger("AttackScream");
}
public void Kill(bool fast = false)
{
//animator.speed = 0;
InLight();
isAlive = false;
foreach (var obj in objectsThatFallOnDeath)
{
obj.AddComponent<Rigidbody>();
if (obj.GetComponent<Collider>() != null) obj.GetComponent<Collider>().enabled = false;
}
var dur = deathDuration;
if (fast)
{
dur = fastDeathduration;
curDeathSpeed = deathSpeed * (deathDuration / fastDeathduration);
}
StartCoroutine(destroyAfterSeconds(dur));
}
private IEnumerator destroyAfterSeconds(float duration)
{
yield return new WaitForSeconds(duration);
Destroy(gameObject);
}
}
}

View File

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

View File

@ -0,0 +1,397 @@
using UnityEngine;
using UnityEngine.AI;
public class SkinlessMonsterComponent : MonoBehaviour
{
[SerializeField] private NavMeshAgent agent;
[SerializeField] private Enemy.SkinlessMonsterAnimator animator;
[SerializeField] private float atTargetDistance = 2;
[SerializeField] private float health = 2f;
[SerializeField] [Tooltip("This is the angle of visibility the enemy has")]
private float visibilityConeLimit = 90f;
[SerializeField] private float bulletSoundRange = 15f;
[SerializeField] private float newTargetCooldown = 5f;
//private bool prePauseStoppedState = false;
[SerializeField] private BoxCollider leftHandDamage;
[SerializeField] private BoxCollider rightHandDamage;
private bool atTarget;
private float distanceToPlayer;
private Item.FlareRegister flareRegister;
private bool inDamageMargin;
private bool inDamageRange;
private bool isAlive = true;
private Vector3 oppositeVector;
private Player.PlayerComponent player;
private TargetInformation target;
private GameObject targetObject;
private float timeSinceTarget;
private void Awake()
{
//Find active player rn.
var players = FindObjectsOfType<Player.PlayerComponent>();
foreach (var p in players)
if (p.isActiveAndEnabled)
player = p;
}
private void Start()
{
flareRegister = FindObjectOfType<Item.FlareRegister>();
if (targetObject == null)
targetObject = new GameObject();
targetObject.name = "Enemy Target";
if (player == null) player = FindObjectOfType<Player.PlayerComponent>();
}
private void Update()
{
if (!player.IsAlive) Stop();
if (target != null) HandleTargetOperations();
CheckForAOERanges();
if (isAlive && player.IsAlive)
SetLiveTargeting();
timeSinceTarget += Time.deltaTime;
if (isAlive)
{
leftHandDamage.enabled = true;
rightHandDamage.enabled = true;
}
else
{
leftHandDamage.enabled = false;
rightHandDamage.enabled = false;
}
/*
AI Behavior:
A. If not targeting player
1. Get distance to player
- if distance < player.NoiseDistance then target player.
2. Raycast to player to test line of sight
- if in line of sight and angle between LOS vector and forward vector is < LOF margin, then
target player.
B. If targeting player
1. If out of sound range and no line of sight then lose target.
- stop()
2. If beacon placed down and in range
- remove agent
- kill()
3. If beacon placed down and in margin:
- stop() and wait for player to leave AOE (enforced by navigation).
*/
}
private void OnTriggerEnter(Collider other)
{
if (other.gameObject.GetComponent<Item.BulletComponent>() != null)
health -= other.gameObject.GetComponent<Item.BulletComponent>().DamageMagnitude;
}
private void HandleTargetOperations()
{
//Update booleans for movement
var distToTarget = Vector3.Distance(target.target.transform.position, agent.transform.position);
atTarget = atTargetDistance >= distToTarget;
if (target.hasDamageRange)
{
inDamageRange = target.damageRange <= distToTarget;
inDamageMargin = target.damageMargin + target.damageRange <= distToTarget;
}
else
{
inDamageRange = false;
inDamageMargin = false;
}
//Perform actions.
if (target.runTowards)
{
if (inDamageRange)
{
//Damage is being dealt
animator.InLight();
//Deal Damage
health -= Time.deltaTime;
if (health < 0 && isAlive) Kill();
}
else if (inDamageMargin)
{
//Effective stop
agent.SetDestination(transform.position);
animator.StopMoving();
}
else
{
if (atTarget)
{
//Effective stop
agent.SetDestination(transform.position);
animator.StopMoving();
if (target.isHostile)
{
animator.Attack();
animator.SetAttackType(Random.Range(0, 0));
}
}
else
{
agent.SetDestination(target.target.transform.position);
animator.StartMoving();
animator.NotInLight();
}
}
}
else
{
//Run away logic
if (atTarget || distToTarget < 3)
{
animator.StopMoving();
}
else
{
var r = new Ray();
r.origin = transform.position;
r.direction = oppositeVector;
RaycastHit hit;
if (Physics.Raycast(r, out hit))
{
animator.StartMoving();
agent.SetDestination(hit.point);
}
else
{
agent.SetDestination(transform.position + oppositeVector * 100);
agent.isStopped = false;
}
}
}
if (atTarget && target.isHostile) SlowLookAt(target.target.transform.position - transform.position);
}
private void SlowLookAt(Vector3 targetVector, float animatedRotationSpeed = 1f)
{
var relativePos = targetVector;
var toRotation = Quaternion.LookRotation(relativePos);
transform.rotation = Quaternion.Lerp(transform.rotation, toRotation, animatedRotationSpeed * Time.deltaTime);
}
private void CheckForAOERanges()
{
foreach (var bullet in flareRegister.bullets)
{
var dist = Vector3.Distance(bullet.transform.position, transform.position);
if (dist <= bullet.DamageRange)
{
health = 0;
Kill(true);
}
}
foreach (var beacon in flareRegister.beacons)
{
var dist = Vector3.Distance(beacon.transform.position, transform.position);
if (dist <= beacon.Range) health = 0f;
}
if (health <= 0) Kill();
}
public bool isPlayerVisible(bool withAngle)
{
var r = new Ray();
r.origin = transform.position;
r.direction = player.transform.position - transform.position;
var toPosition = (player.transform.position - transform.position).normalized;
var angleToPosition = Vector3.Angle(transform.forward, toPosition);
RaycastHit hit;
if (Physics.Raycast(r, out hit))
{
var hitObject = hit.transform.gameObject;
if (hitObject.GetComponent<Player.PlayerComponent>() != null)
//hit player
return angleToPosition <= visibilityConeLimit || !withAngle;
if (hitObject.GetComponentInParent<Player.PlayerComponent>() != null)
//also hit player
return angleToPosition <= visibilityConeLimit || !withAngle;
}
return false;
}
private void SetLiveTargeting()
{
if (!isAlive)
//this.targetObject.transform.position = transform.position;
Stop();
distanceToPlayer = Vector3.Distance(transform.position, player.transform.position);
//print("Dist Comparison "+distanceToPlayer.ToString()+" Noise:"+player.NoiseManager.NoiseDistance);
var isPlayerVisible = this.isPlayerVisible(true);
//check if player is heard or player line of sight
if (distanceToPlayer <= player.NoiseManager.NoiseDistance || isPlayerVisible)
{
//check that nothing in between
if (this.isPlayerVisible(false)) Target(player.gameObject, true);
}
else
{
if (timeSinceTarget < newTargetCooldown)
//no further targeting
//Stop();
return;
Item.BulletComponent closestBullet = null;
var closestDistance = Mathf.Infinity;
foreach (var bullet in flareRegister.bullets)
{
var bDist = Vector3.Distance(bullet.transform.position, transform.position);
if (closestBullet == null || (bDist < bulletSoundRange && bDist < closestDistance))
{
closestBullet = bullet;
closestDistance = bDist;
}
}
if (closestBullet != null && closestBullet.DamageRange == 0)
{
targetObject.transform.position = closestBullet.transform.position;
Target(targetObject);
}
else
{
targetObject.transform.position = transform.position;
Target(targetObject);
Stop();
}
}
}
/*
STANDARD BEHAVIOR:
- OnSeeing/Hearing Player:
- Run towards Player
- OnHearing Bolt:
- Run towards bolt
- OnSeeing Flare:
- Run towards flare if not within (flareRange + flareMargin).
- This acts like if you are far enough away that you don't feel the pain of the flare
- OnSeeing FlareBeacon:
- Run away if within (flareBeaconRange + flareBeaconMargin).
*/
//Runs towards target. If its meant to be hostile, it will melee attack once in range.
public void Target(GameObject obj, bool hostile = false)
{
if (target == null || target.target != obj)
{
//target = new TargetInformation(obj,hostile,false,runTowards:true);
target = new TargetInformation();
target.target = obj;
target.isHostile = hostile;
target.hasDamageRange = false;
target.runTowards = true;
timeSinceTarget = 0;
}
}
//Runs towards flare such that it stops randomly within margin before range.
public void TargetFlare(GameObject obj, float range, float margin)
{
if (target == null || target.target != obj)
{
//target = new TargetInformation(obj, false, true, range, margin,runTowards:true);
target = new TargetInformation();
target.target = obj;
target.isHostile = false;
target.hasDamageRange = true;
target.damageRange = range;
target.damageMargin = margin;
target.runTowards = true;
timeSinceTarget = 0;
}
}
/// <summary>
/// Runs away from object. A minimum range is specified where it no longer takes damage, and a minimum margin is
/// speicifed where it can stop running.
/// </summary>
/// <param name="obj"></param>
/// <param name="minRange"></param>
/// <param name="minMargin"></param>
public void RunAwayFrom(GameObject obj, float minRange, float minMargin)
{
if (target == null || target.target != obj)
{
//target = new TargetInformation(obj, false, true, minRange, minMargin, false);
target = new TargetInformation();
target.target = obj;
target.isHostile = false;
target.hasDamageRange = true;
target.damageRange = minRange;
target.damageMargin = minMargin;
target.runTowards = false;
oppositeVector = -(target.target.transform.position - transform.position).normalized;
timeSinceTarget = 0;
}
}
public void Stop()
{
target = new TargetInformation();
target.target = gameObject;
target.isHostile = false;
target.hasDamageRange = false;
target.runTowards = true;
}
public void Kill(bool fast = false)
{
if (isAlive)
{
animator.Kill(fast);
isAlive = false;
agent.isStopped = true;
}
}
}
internal class TargetInformation
{
public float damageMargin;
public float damageRange;
public bool hasDamageRange;
public bool isHostile;
public bool runTowards;
public GameObject target;
}

View File

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

View File

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

View File

@ -0,0 +1,22 @@
using UnityEngine;
public class TestSkinnlessMonster : MonoBehaviour
{
[SerializeField] private SkinlessMonsterComponent monster;
[SerializeField] private Camera cam;
// Start is called before the first frame update
private void Start()
{
}
// Update is called once per frame
private void Update()
{
if (Input.GetKeyDown(KeyCode.Alpha1)) monster.Target(cam.gameObject, true);
if (Input.GetKeyDown(KeyCode.Alpha2)) monster.TargetFlare(cam.gameObject, 1, 1);
if (Input.GetKeyDown(KeyCode.Alpha3)) monster.RunAwayFrom(cam.gameObject, 1, 1);
if (Input.GetKeyDown(KeyCode.Alpha0)) monster.Stop();
}
}

View File

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

View File

@ -0,0 +1,25 @@
using UnityEngine;
namespace Enemy
{
public class DummyComponent : MonoBehaviour
{
private Animator anim;
// Start is called before the first frame update
private void Start()
{
anim = GetComponentInParent<Animator>();
}
// Update is called once per frame
private void Update()
{
}
private void OnCollisionEnter(Collision collision)
{
if (collision.gameObject.GetComponent<Item.BulletComponent>() != null) anim.Play("DummyFall");
}
}
}

View File

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

View File

@ -0,0 +1,24 @@
using UnityEngine;
namespace Enemy {
public class MonsterComponent : MonoBehaviour
{
[SerializeField] private float attackDamage = 1f;
[SerializeField] private bool shakeCameraOnHit = true;
public float AttackDamage => attackDamage;
public bool ShakeCameraOnHit => shakeCameraOnHit;
// Start is called before the first frame update
private void Start()
{
}
// Update is called once per frame
private void Update()
{
}
}
}

View File

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

View File

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

View File

@ -0,0 +1,88 @@
using UnityEngine;
[RequireComponent(typeof(Animator))]
public class IKControl_Robot : MonoBehaviour
{
public bool ikActive;
public Transform rightHandObj;
public Transform leftHandObj;
public Transform lookObj;
public Transform stepOnObj;
public Transform stepOffObj;
protected Animator animator;
private void Start()
{
animator = GetComponent<Animator>();
transform.Rotate(0, 90, 0);
}
//a callback for calculating IK
private void OnAnimatorIK()
{
if (animator)
{
//if the IK is active, set the position and rotation directly to the goal.
if (ikActive)
{
// Set the look target position, if one has been assigned
if (lookObj != null)
{
animator.SetLookAtWeight(1);
animator.SetLookAtPosition(lookObj.position);
}
// Set the right hand target position and rotation, if one has been assigned
if (rightHandObj != null)
{
animator.SetIKPositionWeight(AvatarIKGoal.RightHand, 1);
animator.SetIKRotationWeight(AvatarIKGoal.RightHand, 1);
animator.SetIKPosition(AvatarIKGoal.RightHand, rightHandObj.position);
animator.SetIKRotation(AvatarIKGoal.RightHand, rightHandObj.rotation);
}
if (leftHandObj != null)
{
animator.SetIKPositionWeight(AvatarIKGoal.LeftHand, 1);
animator.SetIKRotationWeight(AvatarIKGoal.LeftHand, 1);
animator.SetIKPosition(AvatarIKGoal.LeftHand, leftHandObj.position);
animator.SetIKRotation(AvatarIKGoal.LeftHand, leftHandObj.rotation);
}
if (stepOnObj != null)
{
animator.SetIKPositionWeight(AvatarIKGoal.LeftFoot, 1);
animator.SetIKRotationWeight(AvatarIKGoal.LeftFoot, 1);
animator.SetIKPosition(AvatarIKGoal.LeftFoot, stepOnObj.position);
animator.SetIKRotation(AvatarIKGoal.LeftFoot, stepOnObj.rotation);
}
if (stepOffObj != null)
{
animator.SetIKPositionWeight(AvatarIKGoal.RightFoot, 1);
animator.SetIKRotationWeight(AvatarIKGoal.RightFoot, 1);
animator.SetIKPosition(AvatarIKGoal.RightFoot, stepOffObj.position);
animator.SetIKRotation(AvatarIKGoal.RightFoot, stepOffObj.rotation);
}
}
//if the IK is not active, set the position and rotation of the hand and head back to the original position
else
{
animator.SetIKPositionWeight(AvatarIKGoal.RightHand, 0);
animator.SetIKRotationWeight(AvatarIKGoal.RightHand, 0);
animator.SetIKPositionWeight(AvatarIKGoal.LeftHand, 0);
animator.SetIKRotationWeight(AvatarIKGoal.LeftHand, 0);
animator.SetLookAtWeight(0);
animator.SetIKPositionWeight(AvatarIKGoal.LeftFoot, 0);
animator.SetIKRotationWeight(AvatarIKGoal.LeftFoot, 0);
animator.SetIKPositionWeight(AvatarIKGoal.RightFoot, 0);
animator.SetIKRotationWeight(AvatarIKGoal.RightFoot, 0);
}
}
}
}

View File

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

View File

@ -0,0 +1,44 @@
using System.Collections;
using UnityEngine;
using UnityEngine.VFX;
public class RobotMouthAnimator : MonoBehaviour
{
[SerializeField] private VisualEffect fireEffect;
[SerializeField] private Light fireLight;
private Animator anim;
// Start is called before the first frame update
private void Start()
{
anim = GetComponent<Animator>();
fireLight.gameObject.SetActive(false);
}
// Update is called once per frame
private void Update()
{
if (Input.GetKeyDown(KeyCode.Return))
{
anim.SetBool("FlapsOpen", !anim.GetBool("FlapsOpen"));
if (anim.GetBool("FlapsOpen"))
{
StartCoroutine(WaitToFire());
}
else
{
fireEffect.Stop();
fireLight.gameObject.SetActive(false);
}
}
}
private IEnumerator WaitToFire()
{
yield return new WaitForSeconds(1.5f);
fireEffect.Play();
fireLight.gameObject.SetActive(true);
}
}

View File

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

View File

@ -0,0 +1,65 @@
using UnityEngine;
using UnityEngine.VFX;
namespace Enemy
{
[ExecuteAlways]
public class SwarmAnimator : MonoBehaviour
{
[SerializeField] private VisualEffect vfx;
[SerializeField] private Rigidbody rb;
//[SerializeField]
//private string parameterName = "DeltaVector";
[SerializeField] private Vector3 avoidancePosDefault;
[SerializeField] private float explodeDuration = 1.0f;
private Vector3 currentPosition;
private float dur;
private bool isExploding;
private Vector3 previousPosition;
// Start is called before the first frame update
private void Start()
{
}
// Update is called once per frame
private void Update()
{
previousPosition = currentPosition;
currentPosition = transform.position;
var velocity = currentPosition - previousPosition;
vfx.SetVector3("DeltaVector", velocity);
if (Input.GetKeyDown(KeyCode.Space)) Explode();
if (isExploding)
{
if (dur > explodeDuration) StopExplode();
dur += Time.deltaTime;
}
}
private void FixedUpdate()
{
}
private void Explode()
{
vfx.SetVector3("Avoid", transform.position);
isExploding = true;
dur = 0;
//Wait a sec then stop.
}
private void StopExplode()
{
vfx.SetVector3("Avoid", avoidancePosDefault);
isExploding = false;
vfx.Stop();
}
}
}

View File

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