imported music, added combat and death
This commit is contained in:
33
Assets/Scripts/CharacterControllerForce.cs
Normal file
33
Assets/Scripts/CharacterControllerForce.cs
Normal file
@ -0,0 +1,33 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class CharacterControllerForce : MonoBehaviour
|
||||
{
|
||||
float mass = 3f; // defines the character mass
|
||||
Vector3 impact = Vector3.zero;
|
||||
private CharacterController character;
|
||||
|
||||
void Start()
|
||||
{
|
||||
|
||||
character = this.gameObject.GetComponent<CharacterController>();
|
||||
}
|
||||
|
||||
// call this function to add an impact force:
|
||||
public void AddImpact(Vector3 dir, float force)
|
||||
{
|
||||
dir.Normalize();
|
||||
if (dir.y < 0) dir.y = -dir.y; // reflect down force on the ground
|
||||
impact += dir.normalized * force / mass;
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
// apply the impact force:
|
||||
if (impact.magnitude > 0.2)
|
||||
character.Move(impact * Time.deltaTime);
|
||||
// consumes the impact energy each cycle:
|
||||
impact = Vector3.Lerp(impact, Vector3.zero, 5 * Time.deltaTime);
|
||||
}
|
||||
}
|
11
Assets/Scripts/CharacterControllerForce.cs.meta
Normal file
11
Assets/Scripts/CharacterControllerForce.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1fb5120753ff7544bb106f2fcaaad636
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -2,6 +2,7 @@ using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor.Rendering;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
|
||||
public class SkinlessMonsterAnimator : MonoBehaviour
|
||||
{
|
||||
@ -9,56 +10,144 @@ public class SkinlessMonsterAnimator : MonoBehaviour
|
||||
private Animator animator;
|
||||
private float speed = 0f;
|
||||
|
||||
[SerializeField]
|
||||
[Tooltip("This is the object with the skin dissolve material")]
|
||||
private GameObject modelObject;
|
||||
[SerializeField]
|
||||
private List<GameObject> objectsThatFallOnDeath= new List<GameObject>();
|
||||
|
||||
private Material dissolveMaterial;
|
||||
private bool isAlive = true;
|
||||
[SerializeField]
|
||||
private float deathSpeed = 5f;
|
||||
private float curDeathSpeed = 5f;
|
||||
|
||||
private bool isRunning = false;
|
||||
public bool IsRunning { get { return isRunning; } }
|
||||
[SerializeField]
|
||||
private float fastDeathduration = 1f;
|
||||
[SerializeField]
|
||||
private float deathDuration = 5f;
|
||||
[SerializeField]
|
||||
private string deathAnimationName = "PainScream";
|
||||
|
||||
|
||||
// Start is called before the first frame update
|
||||
void Start()
|
||||
{
|
||||
|
||||
dissolveMaterial = modelObject.GetComponent<SkinnedMeshRenderer>().materials[0];
|
||||
curDeathSpeed = deathSpeed;
|
||||
}
|
||||
|
||||
// Update is called once per frame
|
||||
void Update()
|
||||
{
|
||||
|
||||
if (isAlive)
|
||||
{
|
||||
animator.SetFloat("Speed", speed);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
float quantity = dissolveMaterial.GetFloat("_DissolveQuantity");
|
||||
quantity = Mathf.Lerp(quantity, -2, Time.deltaTime *curDeathSpeed);
|
||||
dissolveMaterial.SetFloat("_DissolveQuantity", quantity);
|
||||
}
|
||||
|
||||
animator.SetFloat("speed", speed);
|
||||
|
||||
|
||||
}
|
||||
|
||||
public void StartMoving()
|
||||
{
|
||||
speed = 1;
|
||||
if (isAlive)
|
||||
{
|
||||
isRunning = true;
|
||||
speed = 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
public void StopMoving()
|
||||
{
|
||||
speed = 0;
|
||||
if (isAlive)
|
||||
{
|
||||
speed = 0;
|
||||
isRunning = false;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
public void Attack()
|
||||
{
|
||||
animator.SetTrigger("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();
|
||||
//animator.Play(this.deathAnimationName);
|
||||
|
||||
isAlive = false;
|
||||
foreach(GameObject obj in this.objectsThatFallOnDeath)
|
||||
{
|
||||
obj.AddComponent<Rigidbody>();
|
||||
if (obj.GetComponent<Collider>() != null)
|
||||
{
|
||||
obj.GetComponent<Collider>().enabled = false;
|
||||
}
|
||||
}
|
||||
float dur = this.deathDuration;
|
||||
if (fast)
|
||||
{
|
||||
dur = this.fastDeathduration;
|
||||
curDeathSpeed = deathSpeed * (this.deathDuration / this.fastDeathduration);
|
||||
}
|
||||
StartCoroutine(destroyAfterSeconds(dur));
|
||||
}
|
||||
|
||||
|
||||
private IEnumerator destroyAfterSeconds(float duration)
|
||||
{
|
||||
yield return new WaitForSeconds(duration);
|
||||
Destroy(this.gameObject);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -12,34 +12,315 @@ public class SkinlessMonsterComponent : MonoBehaviour
|
||||
private NavMeshAgent agent;
|
||||
[SerializeField]
|
||||
private SkinlessMonsterAnimator animator;
|
||||
|
||||
private bool inRangeOfTarget = false;
|
||||
private bool inDamageRange = false;
|
||||
private bool inDamageMargin = false;
|
||||
private bool atTarget = false;
|
||||
[SerializeField]
|
||||
private float atTargetDistance = 3;
|
||||
private float atTargetDistance = 2;
|
||||
private TargetInformation target;
|
||||
|
||||
[SerializeField]
|
||||
private float health = 2f;
|
||||
|
||||
private void Update()
|
||||
|
||||
private bool isAlive = true;
|
||||
|
||||
|
||||
|
||||
private Vector3 oppositeVector;
|
||||
|
||||
private PlayerComponent player;
|
||||
private float distanceToPlayer;
|
||||
private FlareRegister flareRegister;
|
||||
[SerializeField]
|
||||
[Tooltip("This is the angle of visibility the enemy has")]
|
||||
private float visibilityConeLimit = 90f;
|
||||
[SerializeField]
|
||||
private float bulletSoundRange = 15f;
|
||||
|
||||
private GameObject targetObject;
|
||||
[SerializeField]
|
||||
private float newTargetCooldown = 5f;
|
||||
private float timeSinceTarget = 0f;
|
||||
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
|
||||
if (target != null)
|
||||
//Find active player rn.
|
||||
PlayerComponent[] players = GameObject.FindObjectsOfType<PlayerComponent>();
|
||||
foreach (PlayerComponent p in players)
|
||||
{
|
||||
//Update booleans for movement
|
||||
float distToTarget = Vector3.Distance(target.target.transform.position, agent.transform.position);
|
||||
atTarget = atTargetDistance >= distToTarget;
|
||||
if (target.hasDamageRange)
|
||||
if (p.isActiveAndEnabled)
|
||||
{
|
||||
inRangeOfTarget = target.damageRange <= distToTarget;
|
||||
player = p;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void Start()
|
||||
{
|
||||
flareRegister = GameObject.FindObjectOfType<FlareRegister>();
|
||||
if (targetObject == null)
|
||||
targetObject = new GameObject();
|
||||
targetObject.name = "Enemy Target";
|
||||
|
||||
}
|
||||
|
||||
void HandleTargetOperations()
|
||||
{
|
||||
//Update booleans for movement
|
||||
float 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 && this.isAlive)
|
||||
{
|
||||
this.Kill();
|
||||
}
|
||||
|
||||
}
|
||||
else if (inDamageMargin)
|
||||
{
|
||||
//Effective stop
|
||||
agent.SetDestination(transform.position);
|
||||
animator.StopMoving();
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
inRangeOfTarget = false;
|
||||
}
|
||||
//Perform actions.
|
||||
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
|
||||
{
|
||||
Ray 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);
|
||||
}
|
||||
}
|
||||
void SlowLookAt(Vector3 targetVector,float animatedRotationSpeed=1f)
|
||||
{
|
||||
Vector3 relativePos = targetVector;
|
||||
Quaternion toRotation = Quaternion.LookRotation(relativePos);
|
||||
|
||||
transform.rotation = Quaternion.Lerp(transform.rotation, toRotation, animatedRotationSpeed * Time.deltaTime);
|
||||
|
||||
}
|
||||
|
||||
void CheckForAOERanges()
|
||||
{
|
||||
foreach(BulletComponent bullet in flareRegister.bullets)
|
||||
{
|
||||
float dist = Vector3.Distance(bullet.transform.position, transform.position);
|
||||
if (dist <= bullet.DamageRange)
|
||||
{
|
||||
this.health = 0;
|
||||
this.Kill(true);
|
||||
}
|
||||
}
|
||||
foreach(FlareBeacon beacon in flareRegister.beacons)
|
||||
{
|
||||
float dist = Vector3.Distance(beacon.transform.position, transform.position);
|
||||
if (dist <= beacon.Range)
|
||||
{
|
||||
this.health = 0f;
|
||||
|
||||
}
|
||||
}
|
||||
if (this.health <= 0)
|
||||
{
|
||||
this.Kill();
|
||||
}
|
||||
}
|
||||
|
||||
public bool isPlayerVisible(bool withAngle)
|
||||
{
|
||||
Ray r = new Ray();
|
||||
r.origin = transform.position;
|
||||
r.direction = player.transform.position - transform.position;
|
||||
Vector3 toPosition = (player.transform.position - transform.position).normalized;
|
||||
float angleToPosition = Vector3.Angle(transform.forward, toPosition);
|
||||
|
||||
|
||||
RaycastHit hit;
|
||||
if(Physics.Raycast(r, out hit))
|
||||
{
|
||||
|
||||
GameObject hitObject = hit.transform.gameObject;
|
||||
|
||||
if (hitObject.GetComponent<PlayerComponent>() != null)
|
||||
{
|
||||
//hit player
|
||||
return angleToPosition <= this.visibilityConeLimit||!withAngle;
|
||||
|
||||
}else if (hitObject.GetComponentInParent<PlayerComponent>() != null)
|
||||
{
|
||||
//also hit player
|
||||
return angleToPosition <= this.visibilityConeLimit||!withAngle;
|
||||
}
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void SetLiveTargeting()
|
||||
{
|
||||
if (!isAlive)
|
||||
{
|
||||
//this.targetObject.transform.position = transform.position;
|
||||
this.Stop();
|
||||
}
|
||||
|
||||
distanceToPlayer = Vector3.Distance(this.transform.position, player.transform.position);
|
||||
//print("Dist Comparison "+distanceToPlayer.ToString()+" Noise:"+player.NoiseManager.NoiseDistance);
|
||||
bool 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))
|
||||
{
|
||||
this.Target(player.gameObject, true);
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
if (this.timeSinceTarget < this.newTargetCooldown)
|
||||
{
|
||||
//no further targeting
|
||||
//Stop();
|
||||
return;
|
||||
}
|
||||
|
||||
BulletComponent closestBullet = null;
|
||||
float closestDistance = Mathf.Infinity;
|
||||
foreach(BulletComponent bullet in this.flareRegister.bullets)
|
||||
{
|
||||
float bDist = Vector3.Distance(bullet.transform.position, transform.position);
|
||||
if (closestBullet==null||(bDist< bulletSoundRange&&bDist<closestDistance))
|
||||
{
|
||||
closestBullet = bullet;
|
||||
closestDistance = bDist;
|
||||
}
|
||||
}
|
||||
if (closestBullet != null)
|
||||
{
|
||||
|
||||
targetObject.transform.position= closestBullet.transform.position;
|
||||
this.Target(targetObject,false);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
targetObject.transform.position = transform.position;
|
||||
this.Target(targetObject,false);
|
||||
this.Stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (!player.IsAlive)
|
||||
{
|
||||
Stop();
|
||||
}
|
||||
|
||||
if (target != null)
|
||||
{
|
||||
HandleTargetOperations();
|
||||
}
|
||||
CheckForAOERanges();
|
||||
if(isAlive&&player.IsAlive)
|
||||
SetLiveTargeting();
|
||||
timeSinceTarget += Time.deltaTime;
|
||||
|
||||
/*
|
||||
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).
|
||||
*/
|
||||
}
|
||||
/*
|
||||
STANDARD BEHAVIOR:
|
||||
@ -58,17 +339,32 @@ public class SkinlessMonsterComponent : MonoBehaviour
|
||||
//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.target!= obj)
|
||||
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.target != obj)
|
||||
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>
|
||||
@ -79,13 +375,53 @@ public class SkinlessMonsterComponent : MonoBehaviour
|
||||
/// <param name="minRange"></param>
|
||||
/// <param name="minMargin"></param>
|
||||
public void RunAwayFrom(GameObject obj,float minRange,float minMargin) {
|
||||
if(target.target != obj)
|
||||
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 = this.gameObject;
|
||||
target.isHostile = false;
|
||||
target.hasDamageRange = false;
|
||||
target.runTowards = true;
|
||||
|
||||
}
|
||||
|
||||
public void Kill(bool fast=false)
|
||||
{
|
||||
if (this.isAlive)
|
||||
{
|
||||
this.animator.Kill(fast);
|
||||
this.isAlive = false;
|
||||
agent.isStopped = true;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
private void OnTriggerEnter(Collider other)
|
||||
{
|
||||
if (other.gameObject.GetComponent<BulletComponent>() != null)
|
||||
{
|
||||
|
||||
this.health -= other.gameObject.GetComponent<BulletComponent>().DamageMagnitude;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
class TargetInformation
|
||||
{
|
||||
|
8
Assets/Scripts/Enemies/AI/Tester.meta
Normal file
8
Assets/Scripts/Enemies/AI/Tester.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: eb4695679f3562e48be282f6f41c7c98
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
38
Assets/Scripts/Enemies/AI/Tester/TestSkinnlessMonster.cs
Normal file
38
Assets/Scripts/Enemies/AI/Tester/TestSkinnlessMonster.cs
Normal file
@ -0,0 +1,38 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class TestSkinnlessMonster : MonoBehaviour
|
||||
{
|
||||
[SerializeField]
|
||||
private SkinlessMonsterComponent monster;
|
||||
[SerializeField]
|
||||
private Camera cam;
|
||||
// Start is called before the first frame update
|
||||
void Start()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// Update is called once per frame
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7669ff0185daae442aef0aafc331fdbb
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
26
Assets/Scripts/Enemies/MonsterComponent.cs
Normal file
26
Assets/Scripts/Enemies/MonsterComponent.cs
Normal file
@ -0,0 +1,26 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class MonsterComponent : MonoBehaviour
|
||||
{
|
||||
|
||||
[SerializeField]
|
||||
private float attackDamage = 1f;
|
||||
public float AttackDamage { get { return this.attackDamage; } }
|
||||
|
||||
[SerializeField]
|
||||
private bool shakeCameraOnHit = true;
|
||||
public bool ShakeCameraOnHit { get { return this.shakeCameraOnHit; } }
|
||||
// Start is called before the first frame update
|
||||
void Start()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// Update is called once per frame
|
||||
void Update()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
11
Assets/Scripts/Enemies/MonsterComponent.cs.meta
Normal file
11
Assets/Scripts/Enemies/MonsterComponent.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 14a29478dda21134ab3eef7c2c3f6d93
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -7,6 +7,7 @@ public class FlareBeacon : MonoBehaviour
|
||||
{
|
||||
[SerializeField]
|
||||
private float range = 1;
|
||||
public float Range { get { return range; }}
|
||||
[SerializeField]
|
||||
private float duration = 5f;
|
||||
|
||||
@ -14,6 +15,7 @@ public class FlareBeacon : MonoBehaviour
|
||||
[SerializeField]
|
||||
private NavMeshObstacle obstacle;
|
||||
|
||||
private FlareRegister register;
|
||||
void OnDrawGizmosSelected()
|
||||
{
|
||||
// Draw a yellow sphere at the transform's position
|
||||
@ -24,6 +26,8 @@ public class FlareBeacon : MonoBehaviour
|
||||
// Start is called before the first frame update
|
||||
void Start()
|
||||
{
|
||||
register = FlareRegister.instance;
|
||||
register.beacons.Add(this);
|
||||
transform.localEulerAngles = new Vector3(-89.98f, 0, 0);
|
||||
Ray r = new Ray();
|
||||
r.direction = -transform.forward;
|
||||
@ -42,6 +46,8 @@ public class FlareBeacon : MonoBehaviour
|
||||
if(Physics.Raycast(r,out hit)){
|
||||
// transform.position = hit.point;
|
||||
}
|
||||
|
||||
if(obstacle!=null)
|
||||
obstacle.radius = this.range / 10;
|
||||
}
|
||||
|
@ -9,11 +9,18 @@ public class BulletComponent : MonoBehaviour
|
||||
private float existed = 0f;
|
||||
[SerializeField]
|
||||
private string type = "flare";
|
||||
|
||||
private FlareRegister register;
|
||||
[SerializeField]
|
||||
private float damageRange = 20f;
|
||||
[SerializeField]
|
||||
private float damageMagnitude = 1f;
|
||||
public float DamageMagnitude { get { return this.damageMagnitude; } }
|
||||
public float DamageRange { get { return damageRange; } }
|
||||
// Start is called before the first frame update
|
||||
void Start()
|
||||
{
|
||||
|
||||
register = FlareRegister.instance;
|
||||
register.bullets.Add(this);
|
||||
}
|
||||
|
||||
// Update is called once per frame
|
||||
@ -25,6 +32,7 @@ public class BulletComponent : MonoBehaviour
|
||||
{
|
||||
if(existed >= duration)
|
||||
{
|
||||
register.bullets.Remove(this);
|
||||
Destroy(this.gameObject);
|
||||
}
|
||||
existed += Time.fixedDeltaTime;
|
||||
|
@ -25,6 +25,7 @@ public class PistolComponent : MonoBehaviour
|
||||
[SerializeField]
|
||||
private float maxProjectileDuration = 5f;
|
||||
|
||||
|
||||
|
||||
|
||||
//private Dictionary<int,float> projectiles = new Dictionary<int, float>();
|
||||
@ -32,7 +33,7 @@ public class PistolComponent : MonoBehaviour
|
||||
// Start is called before the first frame update
|
||||
void Start()
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
|
||||
// Update is called once per frame
|
||||
@ -66,7 +67,7 @@ public class PistolComponent : MonoBehaviour
|
||||
{
|
||||
targetObject.gameObject.transform.position = hit.point;
|
||||
float drop = CalculateDrop(this.bulletSpawnPoint.position, hit.point, this.transform.up * this.firePower);
|
||||
print(drop);
|
||||
//print(drop);
|
||||
|
||||
}
|
||||
}
|
||||
@ -84,6 +85,8 @@ public class PistolComponent : MonoBehaviour
|
||||
Rigidbody pRigid = projectile.GetComponent<Rigidbody>();
|
||||
pRigid.AddForce(pRigid.transform.up*this.firePower, ForceMode.Impulse);
|
||||
projectile.transform.parent = null;
|
||||
|
||||
|
||||
|
||||
}
|
||||
public void Enable()
|
||||
|
8
Assets/Scripts/Item/Registers.meta
Normal file
8
Assets/Scripts/Item/Registers.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 90f48ba02e4248644b7c711ebd9b212f
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
24
Assets/Scripts/Item/Registers/FlareRegister.cs
Normal file
24
Assets/Scripts/Item/Registers/FlareRegister.cs
Normal file
@ -0,0 +1,24 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class FlareRegister : MonoBehaviour
|
||||
{
|
||||
public List<BulletComponent> bullets= new List<BulletComponent>();
|
||||
|
||||
public List<FlareBeacon> beacons= new List<FlareBeacon>();
|
||||
|
||||
public static FlareRegister instance;
|
||||
|
||||
// Start is called before the first frame update
|
||||
void Start()
|
||||
{
|
||||
instance = this;
|
||||
}
|
||||
|
||||
// Update is called once per frame
|
||||
void Update()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
11
Assets/Scripts/Item/Registers/FlareRegister.cs.meta
Normal file
11
Assets/Scripts/Item/Registers/FlareRegister.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 788a4240e87c8654fa8813057977c848
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -34,10 +34,12 @@ public class SpecialItemCycler : MonoBehaviour
|
||||
private TMP_Text selectedQuantityText;
|
||||
private Color sqtInitColor;
|
||||
|
||||
|
||||
// Start is called before the first frame update
|
||||
void Start()
|
||||
{
|
||||
sqtInitColor = selectedQuantityText.color;
|
||||
sqtInitColor = selectedQuantityText.color;
|
||||
|
||||
}
|
||||
|
||||
// Update is called once per frame
|
||||
@ -81,7 +83,7 @@ public class SpecialItemCycler : MonoBehaviour
|
||||
instance.transform.localPosition = Vector3.zero;
|
||||
instance.transform.parent = null;
|
||||
invent.Remove(spawnableItems[spawnableIndex].name);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
72
Assets/Scripts/Player/NoiseVisibilitySettingsManager.cs
Normal file
72
Assets/Scripts/Player/NoiseVisibilitySettingsManager.cs
Normal file
@ -0,0 +1,72 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
|
||||
public class NoiseVisibilitySettingsManager : MonoBehaviour
|
||||
{
|
||||
[SerializeField]
|
||||
private float sneakNoiseDistance = 5f;
|
||||
[SerializeField]
|
||||
private float runNoiseDistance = 10f;
|
||||
[SerializeField]
|
||||
private float shootNoiseDistance = 30f;
|
||||
[SerializeField]
|
||||
private float standNoiseDistance = 0f;
|
||||
private float noiseDistance = 0f;
|
||||
|
||||
public float SneakNoiseDistance { get { return sneakNoiseDistance; } }
|
||||
public float RunNoiseDistance { get { return runNoiseDistance; } }
|
||||
public float ShootNoiseDistance { get { return shootNoiseDistance; } }
|
||||
public float StandNoiseDistance { get { return standNoiseDistance; } }
|
||||
|
||||
public float NoiseDistance { get { return this.noiseDistance; } }
|
||||
|
||||
private float timeSinceLastShot = 0f;
|
||||
[SerializeField]
|
||||
private float shootNoiseDuration = 2f;
|
||||
private bool isSneaking = false;
|
||||
private bool isRunning = false;
|
||||
|
||||
|
||||
// Start is called before the first frame update
|
||||
void Start()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// Update is called once per frame
|
||||
void Update()
|
||||
{
|
||||
if (timeSinceLastShot>0)
|
||||
{
|
||||
this.noiseDistance = this.shootNoiseDistance;
|
||||
}
|
||||
else if (isRunning)
|
||||
{
|
||||
this.noiseDistance = this.runNoiseDistance;
|
||||
}else if (isSneaking)
|
||||
{
|
||||
this.noiseDistance = this.sneakNoiseDistance;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.noiseDistance = standNoiseDistance;
|
||||
}
|
||||
|
||||
timeSinceLastShot -= Time.deltaTime;
|
||||
}
|
||||
|
||||
public void ShotFired()
|
||||
{
|
||||
this.timeSinceLastShot = this.shootNoiseDuration;
|
||||
}
|
||||
public void SetRunning(bool isRunning)
|
||||
{
|
||||
this.isRunning = isRunning;
|
||||
}
|
||||
public void SetSneaking(bool isSneaking)
|
||||
{
|
||||
this.isSneaking= isSneaking;
|
||||
}
|
||||
}
|
11
Assets/Scripts/Player/NoiseVisibilitySettingsManager.cs.meta
Normal file
11
Assets/Scripts/Player/NoiseVisibilitySettingsManager.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1179093e6fa69e045838868718a12c58
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -42,9 +42,10 @@ public class PlayerAnimationController : MonoBehaviour
|
||||
}
|
||||
}
|
||||
|
||||
public void Hit()
|
||||
public void Hit(bool isDead)
|
||||
{
|
||||
animController.SetTrigger("WasHit");
|
||||
animController.SetBool("IsDead", isDead);
|
||||
}
|
||||
|
||||
// Start is called before the first frame update
|
||||
|
98
Assets/Scripts/Player/PlayerComponent.cs
Normal file
98
Assets/Scripts/Player/PlayerComponent.cs
Normal file
@ -0,0 +1,98 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using Cinemachine;
|
||||
|
||||
|
||||
public class PlayerComponent : MonoBehaviour
|
||||
{
|
||||
[SerializeField]
|
||||
private float health = 5f;
|
||||
[SerializeField]
|
||||
private float maxHealth = 5f;
|
||||
[SerializeField]
|
||||
private float stamina = 20f;
|
||||
[SerializeField]
|
||||
private float maxStamina = 20f;
|
||||
|
||||
[SerializeField] private NoiseVisibilitySettingsManager noiseManager;
|
||||
[SerializeField] private PlayerMovementController movementController;
|
||||
|
||||
public NoiseVisibilitySettingsManager NoiseManager { get { return this.noiseManager; } }
|
||||
public PlayerMovementController MovementController { get { return movementController; } }
|
||||
[SerializeField]
|
||||
private PlayerAnimationController animationController;
|
||||
|
||||
[HideInInspector]
|
||||
public FlareRegister flareRegister;
|
||||
[SerializeField]
|
||||
private CinemachineFreeLook cameraFreeLook;
|
||||
private float shakeTimer = 0;
|
||||
CinemachineBasicMultiChannelPerlin perlin;
|
||||
[SerializeField]
|
||||
private float knockbackDuration = 1f;
|
||||
[SerializeField]
|
||||
private float knockbackDistance = 5f;
|
||||
[HideInInspector]
|
||||
public bool IsAlive { get { return this.health > 0; } }
|
||||
private void Awake()
|
||||
{
|
||||
flareRegister = GameObject.FindObjectOfType<FlareRegister>();
|
||||
}
|
||||
// Start is called before the first frame update
|
||||
void Start()
|
||||
{
|
||||
perlin = cameraFreeLook.GetRig(1).GetCinemachineComponent<CinemachineBasicMultiChannelPerlin>();
|
||||
}
|
||||
|
||||
// Update is called once per frame
|
||||
void Update()
|
||||
{
|
||||
NoiseManager.SetRunning(MovementController.IsRunning);
|
||||
|
||||
if (shakeTimer > 0)
|
||||
{
|
||||
shakeTimer -= Time.deltaTime;
|
||||
|
||||
// perlin.m_AmplitudeGain = 0;
|
||||
perlin.m_AmplitudeGain = Mathf.Lerp(perlin.m_AmplitudeGain, 0, .1f);
|
||||
if (shakeTimer <= 0f)
|
||||
{
|
||||
|
||||
perlin.m_AmplitudeGain = 0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void ShakeCamera(float intensity, float time)
|
||||
{
|
||||
CinemachineBasicMultiChannelPerlin perlin = cameraFreeLook.GetRig(1).GetCinemachineComponent<CinemachineBasicMultiChannelPerlin>();
|
||||
perlin.m_AmplitudeGain= intensity;
|
||||
shakeTimer = time;
|
||||
}
|
||||
|
||||
public void Damage(float damage,bool applyShake=false)
|
||||
{
|
||||
this.health-=damage;
|
||||
if (applyShake)
|
||||
{
|
||||
ShakeCamera(15, 5);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnTriggerEnter(Collider other)
|
||||
{
|
||||
if (other.CompareTag("Damaging"))
|
||||
{
|
||||
MonsterComponent monster = other.GetComponentInParent<MonsterComponent>();
|
||||
|
||||
this.Damage(monster.AttackDamage, monster.ShakeCameraOnHit);
|
||||
animationController.Hit(this.health<=0);
|
||||
this.movementController.PhysicalForceMove((transform.position - monster.transform.position)*knockbackDistance);
|
||||
this.movementController.LockMovement(this.knockbackDuration);
|
||||
}
|
||||
}
|
||||
}
|
11
Assets/Scripts/Player/PlayerComponent.cs.meta
Normal file
11
Assets/Scripts/Player/PlayerComponent.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 86fd72b889d47804e844e0bc9c04218d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -38,6 +38,9 @@ public class PlayerInteractionHandler : MonoBehaviour
|
||||
private bool useItemSelector = true;
|
||||
[SerializeField]
|
||||
private PistolComponent pistol;
|
||||
[SerializeField]
|
||||
private NoiseVisibilitySettingsManager noiseManager;
|
||||
|
||||
|
||||
|
||||
// Start is called before the first frame update
|
||||
@ -83,6 +86,7 @@ public class PlayerInteractionHandler : MonoBehaviour
|
||||
if (tempInvent.GetQuantityOf(this.pistol.projectileName) > 0)
|
||||
{
|
||||
this.pistol.Fire();
|
||||
this.noiseManager.ShotFired();
|
||||
tempInvent.Remove(this.pistol.projectileName);
|
||||
}
|
||||
|
||||
|
@ -12,9 +12,12 @@ public class PlayerMovementController : MonoBehaviour
|
||||
private float mouseX = 0;
|
||||
|
||||
private bool isRunning = false;
|
||||
private bool isSneaking = false;
|
||||
public bool IsRunning { get { return isRunning; } }
|
||||
[SerializeField]
|
||||
private CharacterController ccontroller;
|
||||
|
||||
private CharacterControllerForce ccForceAddon;
|
||||
|
||||
[SerializeField]
|
||||
private CameraController cameraController;
|
||||
|
||||
@ -31,13 +34,27 @@ public class PlayerMovementController : MonoBehaviour
|
||||
[HideInInspector]
|
||||
public bool AllowRotation = false;
|
||||
|
||||
[SerializeField]
|
||||
private NoiseVisibilitySettingsManager noiseSettings;
|
||||
|
||||
|
||||
|
||||
|
||||
public float NoiseDistance { get { return this.noiseSettings.NoiseDistance; } }
|
||||
|
||||
|
||||
private Vector3 lookingDirectionVector;
|
||||
|
||||
private bool movementLocked = false;
|
||||
private void GetMovementOld()
|
||||
{
|
||||
x = Input.GetAxis("Horizontal");
|
||||
y = Input.GetAxis("Vertical");
|
||||
if (movementLocked)
|
||||
{
|
||||
x = 0;
|
||||
y = 0;
|
||||
}
|
||||
isRunning = (Mathf.Abs(y) > 0.1f || Mathf.Abs(x) > 0.1f);
|
||||
}
|
||||
private void MovePlayer()
|
||||
@ -64,13 +81,14 @@ public class PlayerMovementController : MonoBehaviour
|
||||
// Start is called before the first frame update
|
||||
void Start()
|
||||
{
|
||||
|
||||
ccForceAddon = ccontroller.gameObject.GetComponent<CharacterControllerForce>();
|
||||
}
|
||||
|
||||
// Update is called once per frame
|
||||
void Update()
|
||||
{
|
||||
AllowRotation = Input.GetMouseButton(1);
|
||||
|
||||
AllowRotation = Input.GetMouseButton(1) || Input.GetAxis("Aim")>0.5f;
|
||||
GetMovementOld();
|
||||
MovePlayer();
|
||||
|
||||
@ -86,8 +104,13 @@ public class PlayerMovementController : MonoBehaviour
|
||||
|
||||
SlowLookAt(this.lookingDirectionVector);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void SlowLookAt(Vector3 targetVector)
|
||||
{
|
||||
Vector3 relativePos = targetVector;
|
||||
@ -96,4 +119,21 @@ public class PlayerMovementController : MonoBehaviour
|
||||
transform.rotation = Quaternion.Lerp(transform.rotation, toRotation, animatedRotationSpeed * Time.deltaTime);
|
||||
|
||||
}
|
||||
|
||||
public void PhysicalForceMove(Vector3 vector)
|
||||
{
|
||||
this.ccontroller.Move(vector);
|
||||
ccForceAddon.AddImpact(vector, vector.magnitude);
|
||||
|
||||
}
|
||||
public void LockMovement(float duration)
|
||||
{
|
||||
StartCoroutine(lockMovement(duration));
|
||||
}
|
||||
private IEnumerator lockMovement(float duration)
|
||||
{
|
||||
movementLocked = true;
|
||||
yield return new WaitForSeconds(duration);
|
||||
movementLocked = false;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user