무기랑 적, 체력까지 만든 뒤, 턴제가 만들어 보고 싶어졌습니다.
그럼 먼저 우리 팀과 적이 있어야 할 것이죠
Player, Enemy를 만들었습니다.
TeamManager, TurnManager, GameManager도 만들었습니다.
오늘은 Player와 Enemy를 설명 하겠습니다.
Player.cs
using System.Collections;
using UnityEngine;
public class Player : MonoBehaviour
{
public string CharacterName;
public int Health = 100;
public int AttackPower = 20;
public float Speed;
public float AttackMoveSpeed = 3f;
private Vector3 originalPosition;
private void Start()
{
originalPosition = transform.position;
}
private void Update()
{
if (Health <= 0)
Destroy(gameObject);
}
public void Attack(Enemy target)
{
if (target != null && target.Health > 0)
{
MoveTo(target.transform.position, () =>
{
target.Health -= AttackPower;
Debug.Log($"{CharacterName}가 {target.CharacterName}를 공격했습니다! (남은 체력: {target.Health})");
MoveTo(originalPosition, null);
}, AttackMoveSpeed);
}
}
public void MoveTo(Vector3 targetPosition, System.Action onComplete = null, float moveSpeed = 5f)
{
StartCoroutine(MoveCoroutine(targetPosition, onComplete, moveSpeed));
}
private IEnumerator MoveCoroutine(Vector3 targetPosition, System.Action onComplete, float moveSpeed)
{
float journeyLength = Vector3.Distance(transform.position, targetPosition);
float startTime = Time.time;
while (Vector3.Distance(transform.position, targetPosition) > 0.1f)
{
float distCovered = (Time.time - startTime) * moveSpeed;
float fractionOfJourney = distCovered / journeyLength;
transform.position = Vector3.Lerp(transform.position, targetPosition, fractionOfJourney);
yield return null;
}
transform.position = targetPosition;
onComplete?.Invoke();
}
}
Player 즉 우리 팀 오브젝트에 사용 할 스크립트 입니다.
public string CharacterName;
public int Health = 100;
public int AttackPower = 20;
public float Speed;
public float AttackMoveSpeed = 3f;
private Vector3 originalPosition;
순서대로 이름, 체력, 공격력, 공격 할 속도, 공격 할 때의 이동 속도, 원래 포지션입니다.
공격 할 속도란 턴제에서 많이 사용되는 속도의 개념입니다.

예시로 붕괴 : 스타레일의 속도 바를 가져 왔습니다.
현재 첫 번째 캐릭터가 제일 위에 있으므로 가장 속도가 빠른 것으로 보입니다.
그 다음으로 속도 순서대로 공격 할 것으로 보이며, 캐릭터 초상화 옆에 숫자는 앞으로 공격까지 남은 수를 뜻합니다.
private void Start()
{
originalPosition = transform.position;
}
private void Update()
{
if (Health <= 0)
Destroy(gameObject);
}
시작 시, 현재 위치를 저장합니다. 그리고 만약 체력이 0 보다 작아지면 오브젝트를 파괴합니다.
public void Attack(Enemy target)
{
if (target != null && target.Health > 0)
{
MoveTo(target.transform.position, () =>
{
target.Health -= AttackPower;
Debug.Log($"{CharacterName}가 {target.CharacterName}를 공격했습니다! (남은 체력: {target.Health})");
MoveTo(originalPosition, null);
}, AttackMoveSpeed);
}
}
공격 메서드입니다. 타겟이 있고, 체력이 0 보다 크면 공격을 합니다.
상대의 체력이 공격력 만큼 깎이며, 디버그로 확인을 할 수 있습니다.
그 다음 이동을 합니다.
public void MoveTo(Vector3 targetPosition, System.Action onComplete = null, float moveSpeed = 5f)
{
StartCoroutine(MoveCoroutine(targetPosition, onComplete, moveSpeed));
}
private IEnumerator MoveCoroutine(Vector3 targetPosition, System.Action onComplete, float moveSpeed)
{
float journeyLength = Vector3.Distance(transform.position, targetPosition);
float startTime = Time.time;
while (Vector3.Distance(transform.position, targetPosition) > 0.1f)
{
float distCovered = (Time.time - startTime) * moveSpeed;
float fractionOfJourney = distCovered / journeyLength;
transform.position = Vector3.Lerp(transform.position, targetPosition, fractionOfJourney);
yield return null;
}
transform.position = targetPosition;
onComplete?.Invoke();
}
MoveTo -> 이동 코루틴을 위한 메서드로 봐도 괜찮습니다.
MoveCoroutine은 간단하게 현재 위치를 저장하고 상대에게 이동한 뒤 다시 돌아오는 메서드입니다.
Enemy.cs
using System.Collections;
using UnityEngine;
public class Enemy : MonoBehaviour
{
public string CharacterName;
public int Health = 100;
public int AttackPower = 15;
public float Speed;
public float AttackMoveSpeed = 3f;
public Transform[] playerTransforms;
private Vector3 originalPosition;
private void Start()
{
originalPosition = transform.position;
GameObject[] playerObjects = GameObject.FindGameObjectsWithTag("Player");
playerTransforms = new Transform[playerObjects.Length];
for (int i = 0; i < playerObjects.Length; i++)
{
playerTransforms[i] = playerObjects[i].transform;
}
}
private void Update()
{
if (Health <= 0)
Destroy(gameObject);
}
public void AttackRandomPlayer()
{
if (playerTransforms.Length > 0)
{
int randomIndex = Random.Range(0, playerTransforms.Length);
Player target = playerTransforms[randomIndex].GetComponent<Player>();
if (target != null && target.Health > 0)
{
MoveTo(target.transform.position, () =>
{
target.Health -= AttackPower;
Debug.Log($"{CharacterName}가 {target.CharacterName}를 공격했습니다! (남은 체력: {target.Health})");
MoveTo(originalPosition, null);
}, AttackMoveSpeed);
}
}
}
public void MoveTo(Vector3 targetPosition, System.Action onComplete = null, float moveSpeed = 5f)
{
StartCoroutine(MoveCoroutine(targetPosition, onComplete, moveSpeed));
}
private IEnumerator MoveCoroutine(Vector3 targetPosition, System.Action onComplete, float moveSpeed)
{
float journeyLength = Vector3.Distance(transform.position, targetPosition);
float startTime = Time.time;
while (Vector3.Distance(transform.position, targetPosition) > 0.1f)
{
float distCovered = (Time.time - startTime) * moveSpeed;
float fractionOfJourney = distCovered / journeyLength;
transform.position = Vector3.Lerp(transform.position, targetPosition, fractionOfJourney);
yield return null;
}
transform.position = targetPosition;
onComplete?.Invoke();
}
}
이동하는 코드는 똑같으니 설명하지 않을 것이고,
public string CharacterName;
public int Health = 100;
public int AttackPower = 15;
public float Speed;
public float AttackMoveSpeed = 3f;
public Transform[] playerTransforms;
private Vector3 originalPosition;
private void Start()
{
originalPosition = transform.position;
GameObject[] playerObjects = GameObject.FindGameObjectsWithTag("Player");
playerTransforms = new Transform[playerObjects.Length];
for (int i = 0; i < playerObjects.Length; i++)
{
playerTransforms[i] = playerObjects[i].transform;
}
}
이름, 체력, 공격력, 속도, 이동 속도, 위치 저장은 같으나, 하나 추가된 점이 있습니다.
바로 우리 팀의 위치입니다.
시작 시, Player 태그를 가진 오브젝트를 받아와서 그 길이만큼 저장을 합니다.
공격을 위한 작업입니다.
public void AttackRandomPlayer()
{
if (playerTransforms.Length > 0)
{
int randomIndex = Random.Range(0, playerTransforms.Length);
Player target = playerTransforms[randomIndex].GetComponent<Player>();
if (target != null && target.Health > 0)
{
MoveTo(target.transform.position, () =>
{
target.Health -= AttackPower;
Debug.Log($"{CharacterName}가 {target.CharacterName}를 공격했습니다! (남은 체력: {target.Health})");
MoveTo(originalPosition, null);
}, AttackMoveSpeed);
}
}
}
위치의 길이 만큼 랜덤으로 돌려서 타겟이 있으면 공격을 합니다.
공격 완성 본입니다.
속도에 따라 공격을 할 수있습니다.
플레이어는 직접 적을 터치하면 공격할 수 있고, 적은 우리 팀 중에서 랜덤으로 공격합니다.
'Unity' 카테고리의 다른 글
| 3D 테스트 프로젝트 10 (0) | 2025.03.03 |
|---|---|
| 3D 테스트 프로젝트 9 (0) | 2025.03.02 |
| 3D 테스트 프로젝트 7 (0) | 2025.02.28 |
| 3D 테스트 프로젝트 6 (0) | 2025.02.27 |
| 3D 테스트 프로젝트 5 (0) | 2025.02.26 |