보스가 큐브로 만들어진 브레스를 뿜고, 뿜은 브레스(큐브들)가 특정위치에 모이면서 뭉쳐지고 뭉쳐지면 큐브 탑이 생김.
- BossAttack.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BossAttack : MonoBehaviour
{
public GameObject cubePrefab; // 큐브 프리팹
public Transform player; // 플레이어
public Transform mouth; // 보스 몬스터의 입 위치
public float force = 500f; // 큐브 발사 힘
public CubeManager cubeManager; // CubeManager 참조
void Start()
{
for (int i = 0; i < 10; i++)
{
// 큐브 생성
GameObject cube = Instantiate(cubePrefab, mouth.position, Quaternion.identity);
// 플레이어 방향으로 발사
Vector3 direction = (player.position - mouth.position).normalized;
cube.GetComponent<Rigidbody>().AddForce(direction * force);
// CubeManager에 생성된 큐브 등록
cubeManager.AddCube(cube);
}
}
}
- CubeManager.cs
using System;
using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
using UnityEngine.AI;
public class CubeManager : MonoBehaviour
{
[SerializeField] List<GameObject> cubes = new List<GameObject>(); // 동적 리스트 선언
private bool isStacked = false;
void Update()
{
//큐브가 모두 모였는지 확인(모두 목표 위치에 도착)
if (!isStacked && AllCubesAreInPosition())
{
// 큐브를 부모-자식 계층으로 연결하여 스택 쌓기
StackCubes();
isStacked = true;
}
//Debug.Log("Cube : " + AllCubesAreInPosition());
}
public void AddCube(GameObject cube)
{
// cubes 리스트에 큐브 추가
cubes.Add(cube); // 큐브 추가
}
public bool AllCubesAreInPosition()
{
// 큐브들이 모두 목표 위치에 도착했는지 확인
foreach (GameObject cube in cubes)
{
if (Vector3.Distance(cube.transform.position, cube.GetComponent<mergeTest>().targetPosition) > 2f)
return false;
}
return true;
}
void StackCubes()
{
Destroy(cubes[0].GetComponent<Rigidbody>());
// 큐브의 Y 높이를 구함 (기본적으로 큐브의 Y scale의 절반을 사용)
float cubeHeight = cubes[0].transform.localScale.y;
cubes[0].transform.rotation = Quaternion.Euler(0, 0, 0);
for (int i = 1; i < cubes.Count; i++)
{
Destroy(cubes[i].GetComponent<Rigidbody>());
cubes[i].transform.rotation = Quaternion.Euler(0, 0, 0);
cubes[i].transform.position = new Vector3(cubes[i-1].transform.position.x, cubes[i - 1].transform.position.y + cubeHeight, cubes[i-1].transform.position.z);
}
// 첫 번째 큐브를 부모로 설정하고 그 위에 큐브를 차례대로 스택 쌓기
for (int i = 1; i < cubes.Count; i++) // 첫 번째 큐브는 기준이므로 i = 1부터 시작
{
cubes[i].transform.parent = cubes[i - 1].transform; // 이전 큐브를 부모로 설정
// 이전 큐브를 부모로 설정 (월드 좌표 유지)
//cubes[i].transform.SetParent(cubes[i - 1].transform, false);
}
// 새로 생긴 큐브 탑에 NavMeshObstacle 추가하기. (지나다니지 못하게 하기 위함)
AddNavMeshObstacle();
// CubeStack 스크립트를 추가하여 추가적인 기능이 필요하면 처리
//CubeStack stackScript = gameObject.AddComponent<CubeStack>();
//stackScript.cubes = cubes;
//stackScript.StackCubes();
// 탑의 마지막 큐브에 IK 적용을 위한 TowerRigging 추가
AddRiggingToTopCube();
}
private void AddNavMeshObstacle()
{
NavMeshObstacle obstacle = cubes[0].AddComponent<NavMeshObstacle>();
obstacle.carving = true; // NavMesh가 이 오브젝트 주변을 실시간으로 업데이트
obstacle.size = new Vector3(1f, 10f, 1f); // 탑의 크기에 맞춰 사이즈 설정
}
void AddRiggingToTopCube()
{
// 탑의 마지막 큐브에 TowerRigging 스크립트를 추가
Transform headCube = cubes[cubes.Count - 1].transform; // 마지막 큐브 선택
TowerRigging rigging = headCube.gameObject.AddComponent<TowerRigging>();
rigging.player = GameObject.FindGameObjectWithTag("Player").transform; // 플레이어 타겟 설정
rigging.headCube = headCube; // 마지막 큐브를 머리로 설정
}
}
- TowerRigging.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Animations.Rigging;
public class TowerRigging : MonoBehaviour
{
public Transform player; // 플레이어 타겟
public Transform headCube; // 탑의 머리 큐브 (마지막 큐브)
void Start()
{
// Rig 설정
Rig rig = headCube.gameObject.AddComponent<Rig>();
// IK ChainIKConstraint 추가
ChainIKConstraint ik = headCube.gameObject.AddComponent<ChainIKConstraint>();
ik.data.target = player; // 플레이어를 타겟으로 설정
}
}
- mergeTest.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class mergeTest : MonoBehaviour
{
public Vector3 targetPosition; // 탑의 일자 위치
public float moveSpeed = 2f; // 이동 속도
GameObject cubeManager;
mergeTest mergeTestV;
private void Start()
{
cubeManager = GameObject.FindGameObjectWithTag("CubeManager");
mergeTestV = GetComponent<mergeTest>();
}
void Update()
{
if( !cubeManager.GetComponent<CubeManager>().AllCubesAreInPosition() )
// 큐브가 3초 후 이동을 시작
StartCoroutine(MoveToTarget());
mergeTestV.enabled = false;
}
IEnumerator MoveToTarget()
{
// 5초 기다림
yield return new WaitForSeconds(3f);
// 큐브를 목표 위치로 이동
while (Vector3.Distance(transform.position, targetPosition) > 1f)
{
transform.position = Vector3.MoveTowards(transform.position, targetPosition, moveSpeed * Time.deltaTime);
yield return null;
}
}
}
유니티 Chain Ik, 체인 IK, 애니메이션 리깅 (0) | 2024.10.04 |
---|---|
유니티 랜덤으로 리스트안의 값을 섞기 (0) | 2024.10.02 |
유니티 내비메쉬(NavMesh) 다시 설정하기, 장애물(Obstacle) 설정하기 (0) | 2024.10.01 |
유니티 오브젝트 부모(상위),자식(하위) 관계 만들기 (0) | 2024.09.30 |
유니티 procedural animation, rigging 연구중 (0) | 2024.09.29 |