bessere Zombies
This commit is contained in:
@ -1,166 +0,0 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using Unity.PlasticSCM.Editor.WebApi;
|
||||
using UnityEngine;
|
||||
|
||||
public class NPC_Behavior : MonoBehaviour
|
||||
{
|
||||
[SerializeField] GameObject confettiEffect;
|
||||
[SerializeField] double eventRate = 1.0; // max 60, min 0 -> how many events are fired per minute
|
||||
[SerializeField] private float _startTime = 30.0f;
|
||||
|
||||
private NPC_EventStack _eventStack;
|
||||
private Text2Speech _text2Speech;
|
||||
private AudioSource _audioSource;
|
||||
|
||||
[SerializeField] private bool _talk = false;
|
||||
[SerializeField] private bool _fullfillNeedManually = false;
|
||||
[SerializeField] private float _timer;
|
||||
[SerializeField] private float _newNeedDelay = 3.0f;
|
||||
[SerializeField] private List<string> _lastTenNeeds = new List<string>();
|
||||
private DeveloperNeeds _developerNeeds;
|
||||
private float _timeBetweenEvents;
|
||||
private GameObject _currentNeed = null;
|
||||
private float _newNeedDelayTimer = 0.0f;
|
||||
private float _effectCreationTime;
|
||||
private GameObject _effect;
|
||||
|
||||
/// <summary>
|
||||
/// The name of the current need
|
||||
/// </summary>
|
||||
public string CurrentNeed => _lastTenNeeds[_lastTenNeeds.Count - 1];
|
||||
/// <summary>
|
||||
/// Indicates if the developer has a need right now
|
||||
/// </summary>
|
||||
public bool HasNeed = false;
|
||||
|
||||
// Start is called before the first frame update
|
||||
void Start()
|
||||
{
|
||||
_developerNeeds = GetComponent<DeveloperNeeds>();
|
||||
_eventStack = GetComponent<NPC_EventStack>();
|
||||
_text2Speech = GetComponent<Text2Speech>();
|
||||
_audioSource = GetComponent<AudioSource>();
|
||||
ResetTimer(_startTime);
|
||||
}
|
||||
|
||||
// Update is called once per frame
|
||||
void Update()
|
||||
{
|
||||
WatchEffect();
|
||||
_timer -= Time.deltaTime;
|
||||
|
||||
if (_newNeedDelayTimer <= 0)
|
||||
{
|
||||
if (_timer <= 0 && _currentNeed == null)
|
||||
{
|
||||
GenerateNeed();
|
||||
ResetTimer();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_newNeedDelayTimer -= Time.deltaTime;
|
||||
}
|
||||
|
||||
// for Debugging
|
||||
if (_fullfillNeedManually)
|
||||
{
|
||||
_fullfillNeedManually = false;
|
||||
NeedFullfilled();
|
||||
}
|
||||
if (_talk)
|
||||
{
|
||||
_talk = false;
|
||||
Talk();
|
||||
}
|
||||
}
|
||||
|
||||
private void ResetTimer(float startTime = 0.0f)
|
||||
{
|
||||
if (eventRate <= 0)
|
||||
{
|
||||
_timeBetweenEvents = float.MaxValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
_timeBetweenEvents = 60f / (float)eventRate;
|
||||
if (startTime > 0)
|
||||
{
|
||||
_timer = startTime;
|
||||
}
|
||||
else
|
||||
{
|
||||
_timer = Random.Range(0.5f * _timeBetweenEvents, 1.25f * _timeBetweenEvents);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void WatchEffect()
|
||||
{
|
||||
if (_effect != null && GetEffectLifetime() >= 3.0f)
|
||||
{
|
||||
RemoveEffect();
|
||||
}
|
||||
}
|
||||
|
||||
private float GetEffectLifetime()
|
||||
{
|
||||
return Time.time - _effectCreationTime;
|
||||
}
|
||||
|
||||
private bool RemoveEffect()
|
||||
{
|
||||
Destroy(_effect);
|
||||
return _effect != null;
|
||||
}
|
||||
|
||||
public bool GenerateNeed(string needName = null)
|
||||
{
|
||||
List<string> needs = new List<string>() { "coffee", "mate", "toilet", "money" };
|
||||
|
||||
string need = needs[UnityEngine.Random.Range(0, needs.Count)];
|
||||
if (needName != null)
|
||||
{
|
||||
need = needName;
|
||||
}
|
||||
|
||||
_currentNeed = _developerNeeds.spawnNeed(need, 0);
|
||||
HasNeed = true;
|
||||
_lastTenNeeds.Add(need);
|
||||
if (_lastTenNeeds.Count > 10)
|
||||
{
|
||||
_lastTenNeeds.RemoveAt(0);
|
||||
}
|
||||
return _currentNeed != null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deletes the current need and its gameobject.
|
||||
/// </summary>
|
||||
/// <returns>bool: wether successfully deleted the gameobject or not</returns>
|
||||
[ContextMenu("Fullfill Need")]
|
||||
public bool NeedFullfilled()
|
||||
{
|
||||
Destroy(_currentNeed);
|
||||
if (HasNeed)
|
||||
{
|
||||
HasNeed = false;
|
||||
_newNeedDelayTimer = _newNeedDelay;
|
||||
_effect = Instantiate(confettiEffect, new Vector3(0.0f, 1.5f, 0.0f), confettiEffect.transform.rotation);
|
||||
_effect.transform.SetParent(transform, false);
|
||||
_effectCreationTime = Time.time;
|
||||
}
|
||||
return _currentNeed == null;
|
||||
}
|
||||
|
||||
public void Talk()
|
||||
{
|
||||
//if (!_audioSource.isPlaying)
|
||||
//{
|
||||
string context = _eventStack.GetEntireContext();
|
||||
_text2Speech.Generate(context);
|
||||
//}
|
||||
}
|
||||
}
|
||||
@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 707d39e7a8ed7a44a8341ead8ee2a9ad
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -1,51 +0,0 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class NPC_EventStack : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private List<string> _eventStack = new List<string>() { "What a great day to develope a game!" };
|
||||
[SerializeField] private int _maxStackHeight = 5;
|
||||
|
||||
private Text2Speech _text2speech;
|
||||
|
||||
public void AddNewContext(string context)
|
||||
{
|
||||
_eventStack.Add(context);
|
||||
if (_eventStack.Count > _maxStackHeight)
|
||||
{
|
||||
_eventStack.RemoveAt(0);
|
||||
}
|
||||
}
|
||||
|
||||
public string GetEntireContext()
|
||||
{
|
||||
string output = "";
|
||||
foreach (string e in _eventStack)
|
||||
{
|
||||
output += e + ", ";
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
public string GetLatestContext()
|
||||
{
|
||||
if (_eventStack.Count > 0)
|
||||
{
|
||||
return _eventStack[_eventStack.Count - 1];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void GenerateVoice()
|
||||
{
|
||||
if ( _eventStack.Count == 0 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
_text2speech.Generate(GetEntireContext());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a5cc0d7ecd7b47f48b2444cff2eb207d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -14,7 +14,13 @@ public class Zombie : MonoBehaviour
|
||||
[SerializeField]
|
||||
List<AudioClip> Noises;
|
||||
[SerializeField]
|
||||
public float speed = 5f;
|
||||
private float _speed = 0.5f;
|
||||
[SerializeField]
|
||||
private float _rotateSpeed = 180.0f;
|
||||
[SerializeField]
|
||||
private float _attackRange = 1.3f;
|
||||
[SerializeField]
|
||||
private float _idleThresholdFactor = 0.2f;
|
||||
[SerializeField]
|
||||
private float _noiseDelay = 5.0f;
|
||||
[SerializeField, ShowOnly]
|
||||
@ -23,24 +29,84 @@ public class Zombie : MonoBehaviour
|
||||
private Rigidbody _rb;
|
||||
private AudioSource _audioSource;
|
||||
private bool _fadeOutNoise = false;
|
||||
private Animator _animator;
|
||||
private bool _isAttacking = false;
|
||||
private float _idleThreshold;
|
||||
private Quaternion _initialRotation;
|
||||
|
||||
|
||||
|
||||
[ContextMenu("Kill Zombie")]
|
||||
private void TestDIe()
|
||||
{
|
||||
Die();
|
||||
}
|
||||
|
||||
void Start()
|
||||
{
|
||||
_rb = GetComponent<Rigidbody>();
|
||||
_noiseTimer = Random.Range(0.3f * _noiseDelay, 1.5f * _noiseDelay);
|
||||
_audioSource = GetComponent<AudioSource>();
|
||||
_animator = GetComponent<Animator>();
|
||||
_idleThreshold = _speed / _idleThresholdFactor;
|
||||
_initialRotation = transform.rotation;
|
||||
}
|
||||
|
||||
void Update()
|
||||
void Update()
|
||||
{
|
||||
//_idleThreshold = _speed / _idleThresholdFactor;
|
||||
|
||||
UpdateNoise();
|
||||
MoveTowardsPlayer();
|
||||
if (!_isAttacking)
|
||||
{
|
||||
MoveTowardsPlayer();
|
||||
}
|
||||
}
|
||||
|
||||
private void MoveTowardsPlayer()
|
||||
{
|
||||
Vector3 direction = (GameManager.Instance.Player.transform.position - transform.position).normalized;
|
||||
_rb.MovePosition(_rb.position + direction * speed * Time.deltaTime);
|
||||
Vector3 direction = (GameManager.Instance.Player.transform.position - transform.position);
|
||||
Quaternion goalRotation = Quaternion.LookRotation(direction);
|
||||
transform.rotation = Quaternion.RotateTowards(transform.rotation, goalRotation, _rotateSpeed * Time.deltaTime);
|
||||
float diff = direction.magnitude;
|
||||
if (diff <= _attackRange && !_isAttacking)
|
||||
{
|
||||
_animator.SetFloat("Running", 0);
|
||||
_animator.SetBool("Idle", false);
|
||||
StartCoroutine(Attack());
|
||||
}
|
||||
else
|
||||
{
|
||||
Vector3 oldPosition = _rb.position;
|
||||
_rb.MovePosition(_rb.position + direction * _speed * Time.deltaTime);
|
||||
float dist = Vector3.Distance(oldPosition, _rb.position);
|
||||
if (dist > _idleThreshold * Time.deltaTime)
|
||||
{
|
||||
_animator.SetBool("Idle", false);
|
||||
_animator.SetFloat("Running", 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
_animator.SetFloat("Running", 0);
|
||||
_animator.SetBool("Idle", true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerator Attack()
|
||||
{
|
||||
_isAttacking = true;
|
||||
_animator.SetBool("Attack", true);
|
||||
yield return new WaitForSeconds(1.5f);
|
||||
_animator.SetBool("Attack", false);
|
||||
// check if actually hit
|
||||
Vector3 direction = (GameManager.Instance.Player.transform.position - transform.position);
|
||||
float diff = direction.magnitude;
|
||||
if (diff <= _attackRange + 0.5f)
|
||||
{
|
||||
GameManager.Instance.Player.GetComponent<Character>().PickupItem(null);
|
||||
}
|
||||
_isAttacking = false;
|
||||
}
|
||||
|
||||
private void UpdateNoise()
|
||||
@ -70,6 +136,15 @@ public class Zombie : MonoBehaviour
|
||||
}
|
||||
}
|
||||
|
||||
private void Die()
|
||||
{
|
||||
GameObject particleEffect = Instantiate(GameManager.Instance.ZombieDeathByDisableParticleEffect, transform.position, Quaternion.Euler(-90, 0, 0), GameManager.Instance.transform);
|
||||
AudioSource audio = particleEffect.GetComponent<AudioSource>();
|
||||
audio.clip = GetComponentInParent<ZombieSpawner>().ZombieDeathByDisableSoundeffects[Random.Range(0, GetComponentInParent<ZombieSpawner>().ZombieDeathByDisableSoundeffects.Count)];
|
||||
audio.Play();
|
||||
Destroy(gameObject);
|
||||
}
|
||||
|
||||
public void FadeOutNoise()
|
||||
{
|
||||
_fadeOutNoise = true;
|
||||
|
||||
@ -8,7 +8,7 @@ public class ZombieSpawner : MonoBehaviour
|
||||
[SerializeField]
|
||||
List<Transform> SpawnPoints;
|
||||
[SerializeField]
|
||||
List<AudioClip> ZombieDeathByDisableSoundeffects;
|
||||
public List<AudioClip> ZombieDeathByDisableSoundeffects;
|
||||
[SerializeField]
|
||||
GameObject ZombiePrefab;
|
||||
[SerializeField]
|
||||
@ -88,7 +88,8 @@ public class ZombieSpawner : MonoBehaviour
|
||||
{
|
||||
if (transform.childCount > _spawnRate) return;
|
||||
Transform pos = SpawnPoints[Random.Range(0, SpawnPoints.Count)];
|
||||
Instantiate(ZombiePrefab, pos.position, Quaternion.identity, transform);
|
||||
Quaternion rotation = Quaternion.Euler(0, Random.Range(0, 359), 0);
|
||||
Instantiate(ZombiePrefab, pos.position, rotation, transform);
|
||||
}
|
||||
|
||||
private void KillZombiesByDisable()
|
||||
|
||||
Reference in New Issue
Block a user