🕹️ 실습 (3D Combat)
Attack Collider
- 애니메이션 녹화버튼을 이용해 공격 콜라이더를 공격 모션에만 활성화 시킴
// Col_PlayerAttk.cs
public Combo combo;
public string type_Attk;
int comboStep;
public string dmg;
public TextMeshProUGUI dmgText;
private void OnEnable() // 오브젝트 활성화되면
{
comboStep = combo.comboStep;
}
private void OnTriggerEnter(Collider other)
{
if (other.CompareTag("HitBox_Enemy"))
{
dmg = $"{type_Attk} {comboStep}";
dmgText.text = dmg;
dmgText.gameObject.SetActive(true);
HitStop.Instance.StopTime();
}
}
HitStop
// HitStop.
public static HitStop Instance;
[Header("Time Settings")]
public float stopTime = 0.1f;
public float timeScaleRecoverySpeed = 10f;
[Header("Camera Shake")]
[SerializeField] private Transform shakeCam;
public float shakeIntensity = 0.1f;
public float shakeFrequency = 0.1f;
private bool isHitStopped;
private Vector3 originalCamPosition;
private Coroutine shakeCoroutine;
private void Awake()
{
if (Instance == null)
{
Instance = this;
}
}
public void StopTime(float intensity = 1f)
{
if (!isHitStopped)
{
isHitStopped = true;
Time.timeScale = 0f;
if (shakeCoroutine != null)
StopCoroutine(shakeCoroutine);
shakeCoroutine = StartCoroutine(ShakeCamera(intensity));
StartCoroutine(ReturnTimeScale());
}
}
private IEnumerator ShakeCamera(float intensity)
{
originalCamPosition = shakeCam.localPosition;
float elapsed = 0f;
while (elapsed < stopTime)
{
float x = Random.Range(-1f, 1f) * shakeIntensity * intensity;
float y = Random.Range(-1f, 1f) * shakeIntensity * intensity;
shakeCam.localPosition = new Vector3(x, y, originalCamPosition.z);
elapsed += Time.unscaledDeltaTime;
yield return new WaitForSecondsRealtime(shakeFrequency);
}
shakeCam.localPosition = originalCamPosition;
}
private IEnumerator ReturnTimeScale()
{
yield return new WaitForSecondsRealtime(stopTime);
while (Time.timeScale < 1f)
{
Time.timeScale = Mathf.MoveTowards(Time.timeScale, 1f, Time.unscaledDeltaTime * timeScaleRecoverySpeed);
yield return null;
}
Time.timeScale = 1f;
isHitStopped = false;
if (shakeCoroutine != null)
{
StopCoroutine(shakeCoroutine);
}
}
public void SetNormalAttack()
{
stopTime = 0.1f;
timeScaleRecoverySpeed = 10;
shakeFrequency = 0.2f;
shakeIntensity = 0.2f;
}
public void SetSmashAttack()
{
stopTime = 0.3f;
timeScaleRecoverySpeed = 5;
shakeFrequency = 0.3f;
shakeIntensity = 0.3f;
}
Minotaurs
// Minotaurs.cs
public Animator anim;
public Transform target;
public float minoSpeed;
bool enableAct;
int atkStep;
Vector3 dir;
string walkStr = "Walk";
string attack1Str = "attack1";
string attack2Str = "attack2";
string attack3Str = "attack3";
void Start()
{
anim = GetComponent<Animator>();
enableAct = true;
}
void Update()
{
if (enableAct)
{
RotateMino();
MoveMino();
}
}
void RotateMino()
{
dir = target.position - transform.position;
transform.localRotation = Quaternion.Slerp(transform.localRotation, Quaternion.LookRotation(dir), 5 * Time.deltaTime);
}
void MoveMino()
{
if (dir.magnitude >= 2)
{
anim.SetBool(walkStr, true);
transform.Translate(Vector3.forward * minoSpeed * Time.deltaTime, Space.Self);
}
else
{
anim.SetBool(walkStr, false);
}
}
void AttackMino() // idle 모션 끝에
{
if (dir.magnitude < 2)
{
switch (atkStep)
{
case 0:
atkStep += 1;
anim.Play(attack1Str);
break;
case 1:
atkStep += 1;
anim.Play(attack2Str);
break;
case 2:
atkStep = 0;
anim.Play(attack3Str);
break;
default:
break;
}
}
}
void FreezeMino() // 공격 모션 시작에
{
enableAct = false;
}
void UnFreezeMino() // 공격 모션 끝에
{
enableAct = true;
}