using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
namespace Test_Portal
{
public class GameManager : MonoBehaviour
{
// 플레이어 정보를 저장할 변수
private static GameObject player;
public static GameEnums.eItemType equippedWeapon = GameEnums.eItemType.None;
public static GameEnums.eItemType equippedShield = GameEnums.eItemType.None;
private void Awake()
{
// 이미 GameManager가 존재한다면 새로운 GameManager를 파괴하여 하나만 유지
if (FindObjectsOfType<GameManager>().Length > 1)
{
Destroy(gameObject);
}
else
{
DontDestroyOnLoad(gameObject);
}
}
// 플레이어 정보를 설정하는 메서드
public static void SetPlayer(GameObject hero)
{
player = hero;
}
// 플레이어 정보를 가져오는 메서드
public static GameObject GetPlayer()
{
return player;
}
// 다음 씬으로 넘어가는 메서드
public static void LoadNextScene(string sceneName)
{
SceneManager.LoadScene(sceneName);
}
public static void EquipWeapon(GameEnums.eItemType weapon)
{
equippedWeapon = weapon;
}
public static void EquipShield(GameEnums.eItemType shield)
{
equippedShield = shield;
}
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Test_Portal
{
public class GameEnums
{
public enum eMonsterType
{
Turtle, Slime
}
public enum eItemType
{
Potion,Sword,Shield,None
}
}
}
using System.Collections;
using System.Collections.Generic;
using Test_Portal;
using UnityEngine;
namespace BossScene
{
public class BossSceneMain : MonoBehaviour
{
[SerializeField] private BossGenerator bossGenerator;
[SerializeField] private Test_Portal.HeroGenerator heroGenerator;
[SerializeField] private GameObject heroPrefab;
private HeroController hero;
private BossController boss;
[SerializeField] private GameObject bossPrefab;
private Camera camera;
private void Awake()
{
camera = Camera.main;
}
void Start()
{
boss = this.bossGenerator.Generate(bossPrefab, new Vector3(3, 0, -3));
if (hero == null)
{
hero = heroGenerator.Generate(heroPrefab, new Vector3(-3, 0, 3));
}
}
private void Update()
{
if (Input.GetMouseButtonUp(1))
{
RaycastHit hit;
if (Physics.Raycast(camera.ScreenPointToRay(Input.mousePosition), out hit))
{
BossController bossHit = hit.collider.GetComponent<BossController>();
if (bossHit != null)
{
}
else
{
if (hero != null)
{
Vector3 targetPos = hit.point;
targetPos.y = hero.transform.position.y;
hero.SetTargetPosition(targetPos);
}
}
}
}
Debug.Log(hero.gameObject.transform.position);
}
}
}
using System.Collections;
using System.Collections.Generic;
using Test_Portal;
using UnityEngine;
namespace Test_Portal
{
public class HeroGenerator : MonoBehaviour
{
private Vector3 savedPosition = Vector3.zero;
public GameObject heroPrefab;
public ItemGenerator itemGenerator;
void Start()
{
}
public HeroController Generate(GameObject prefab, Vector3 initPosition)
{
GameObject heroInstance = Instantiate(prefab);
heroInstance.tag = "Hero";
heroInstance.transform.position = initPosition;
HeroController heroController = heroInstance.GetComponent<HeroController>();
// 장착된 무기 확인 후 장착
if (GameManager.equippedWeapon != GameEnums.eItemType.None)
{
ItemController weaponItem = itemGenerator.Generate(GameManager.equippedWeapon, heroInstance.transform.position);
heroController.EquipItem(weaponItem);
}
// 장착된 방패 확인 후 장착
if (GameManager.equippedShield != GameEnums.eItemType.None)
{
ItemController shieldItem = itemGenerator.Generate(GameManager.equippedShield, heroInstance.transform.position);
heroController.EquipItem(shieldItem);
}
return heroController;
}
}
}
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Test_Boss;
namespace Test_Portal
{
public class HeroController : MonoBehaviour
{
public float moveSpeed = 5.0f;
private Vector3 targetPosition;
public static event Action<ItemController> onItemCollected;
private Animator heroAnimator;
private bool isInAttackAnimation = false;
private float turnSpeed = 10.0f;
public GameObject hitParticlePrefab;
// 공격 대상이 되는 몬스터
private MonsterController attackTarget = null;
private BossController attackBoss = null;
public float attackRange = 2f;
private void Start()
{
targetPosition = transform.position;
heroAnimator = GetComponent<Animator>();
StartCoroutine(HeroMovementUpdate());
}
private IEnumerator HeroMovementUpdate()
{
while (true)
{
if (attackTarget != null)
{
float distance = Vector3.Distance(transform.position, attackTarget.transform.position);
if (distance <= attackRange)
{
if (!isInAttackAnimation)
{
isInAttackAnimation = true;
heroAnimator.SetInteger("state", 2);
yield return new WaitForSeconds(0.5f);
isInAttackAnimation = false;
continue;
}
}
}
if (attackBoss != null)
{
float distance = Vector3.Distance(transform.position, attackTarget.transform.position);
if (distance <= attackRange)
{
if (!isInAttackAnimation)
{
isInAttackAnimation = true;
heroAnimator.SetInteger("state", 2);
yield return new WaitForSeconds(0.5f);
isInAttackAnimation = false;
continue;
}
}
}
if (Vector3.Distance(transform.position, targetPosition) > 0.1f)
{
Quaternion targetRotation = Quaternion.LookRotation(targetPosition - transform.position);
transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, turnSpeed * Time.deltaTime);
transform.position = Vector3.MoveTowards(transform.position, targetPosition, moveSpeed * Time.deltaTime);
if (!isInAttackAnimation)
{
heroAnimator.SetInteger("state", 1);
}
}
else
{
if (!isInAttackAnimation)
{
heroAnimator.SetInteger("state", 0);
}
}
yield return null;
}
}
public void TriggerAttack()
{
if (attackTarget)
{
GameObject hitParticle = Instantiate(hitParticlePrefab, attackTarget.transform.position, Quaternion.identity);
Destroy(hitParticle, 3f);
attackTarget.Die();
isInAttackAnimation = false;
attackTarget = null;
targetPosition = transform.position;
}
}
public void SetAttackTarget(MonsterController monster)
{
attackTarget = monster;
Vector3 directionToMonster = (monster.transform.position - transform.position).normalized;
Vector3 attackPosition = monster.transform.position - directionToMonster * (attackRange * 0.19f);
SetTargetPosition(attackPosition);
}
public void SetAttackBoss(BossController boss)
{
attackBoss = boss;
Vector3 directionToMonster = (boss.transform.position - transform.position).normalized;
Vector3 attackPosition = boss.transform.position - directionToMonster * (attackRange * 0.19f);
SetTargetPosition(attackPosition);
}
public void SetTargetPosition(Vector3 position)
{
targetPosition = position;
}
public void CollectItem(ItemController item)
{
EquipItem(item);
onItemCollected?.Invoke(item);
}
public void EquipItem(ItemController item)
{
GameEnums.eItemType itemType = item.itemType;
switch (itemType)
{
case GameEnums.eItemType.Sword:
EquipToSlot(item.gameObject, "Weapon");
GameManager.EquipWeapon(itemType);
break;
case GameEnums.eItemType.Shield:
EquipToSlot(item.gameObject, "Shield");
GameManager.EquipShield(itemType);
break;
case GameEnums.eItemType.Potion:
break;
}
}
private void EquipToSlot(GameObject item, string slotName)
{
Transform slotTransform = FindChildWithName(this.transform, slotName);
if (slotTransform == null)
{
Debug.LogError("Cannot find slot with name: " + slotName);
return;
}
foreach (Transform child in slotTransform)
{
Destroy(child.gameObject);
}
Destroy(item.GetComponent<BoxCollider>());
item.transform.SetParent(slotTransform);
item.transform.localPosition = Vector3.zero;
item.transform.localRotation = Quaternion.identity;
}
private Transform FindChildWithName(Transform parent, string name)
{
foreach (Transform child in parent)
{
if (child.name == name)
{
return child;
}
Transform found = FindChildWithName(child, name);
if (found != null)
{
return found;
}
}
return null;
}
}
}
씬 넘어가면서 Hero를 동적생성할때 자꾸 생성 오류가 났는데,
그 이유가 Main에서 hero Controller가 null일때 Hero를 동적생성을 하는데
Hero Controller를 [SerializeField]로 선언하고 inspector창에서 Hero Controller를 할당해서
null이 아니라 생긴 오류였다. 앞으로는 잘 확인하자.
반응형
'KDT > 유니티 기초' 카테고리의 다른 글
스레드와(Thread) 코루틴(Coroutine)의 차이 (0) | 2023.08.15 |
---|---|
프로세스(Process), 스레드 (Thread) 그리고 코루틴 (Coroutine) (0) | 2023.08.15 |
동기와 비동기란 무엇일까? (0) | 2023.08.15 |
[SimpleRPG] 보스전 구현(2) 탐지 범위 수정 (0) | 2023.08.14 |
[SimpleRPG] 보스전 구현 (1) (0) | 2023.08.14 |