목차
앵그리버드 만들기
24.12.26
발사 궤적 구현
: Slingshot.cs에 코드 추가
>> 발사 궤적 구현을 위한 변수 선언
public GameObject trajectory;
private List<GameObject> trajectoryObjects = new List<GameObject>();
public int maxStep = 20; // 궤적의 최대 점 수 --> 작을수록 궤적이 짧아진다
public float timeStep = 0.1f; // 시간 간격 --> 작을수록 점이 촘촘해진다
>> 발사 궤적 구현
void PredictTrajectory(Vector3 force)
{
ClearTrajectory();
Vector3 position = center.position;
Vector3 velocity = force / bird.mass; // 물체의 초기 속도 (F = ma --> v = F/m)
for (int i = 0; i < maxStep; i++)
{
float timeElapsed = timeStep * i; // timeElapsed : 현재까지 경과 시간
Vector3 gravity = Physics.gravity;
// 등가속도 운동 --> 각 시간 간격마다 계산된 물체의 위치를 리스트에 추가
Vector3 trajectoryPoint = position +
velocity * timeElapsed +
gravity * (0.5f * timeElapsed * timeElapsed);
var trajectoryObject = Instantiate(trajectory, trajectoryPoint, Quaternion.identity);
trajectoryObjects.Add(trajectoryObject);
}
}
private void ClearTrajectory()
{
foreach (var obj in trajectoryObjects)
{
Destroy(obj);
}
trajectoryObjects.Clear();
}
※ 등가속도 운동
>> 마우스를 눌렀을 때 발사 궤적 표시
void Update()
{
if (isMouseDown && MainCamera != null)
{
Vector3 mousePosition = Input.mousePosition;
mousePosition.z = 10;
currentPosition = MainCamera.ScreenToWorldPoint(mousePosition);
currentPosition = center.position + Vector3.ClampMagnitude(currentPosition - center.position, maxDistance);
currentPosition = ClampBoundary(currentPosition);
SetStrips(currentPosition);
if (birdCollider) // 안정성 --> Shoot()에서 null로 설정했기 때문에
{
birdCollider.enabled = true; // bird를 마우스로 당길 때, Collider가 필요
}
Vector3 birdForce = (currentPosition - center.position) * (force * -1);
PredictTrajectory(birdForce);
}
else
{
ResetStrips();
ClearTrajectory();
}
}
└ 표시되는 궤적과 실제 발사되는 궤적이 다른 문제(보완 완료)
: 표시되는 궤적은 새총의 중심을 출발점으로 계산하고 있지만 실제 발사되는 궤적은 새를 끌어당긴 지점을 출발점으로 계산하고 있기 때문에 차이가 발생
>> Bird.cs
void PredictTrajectory(Vector3 force)
{
ClearTrajectory();
Vector3 position = currentPosition; // center.position --> currentPosition으로 수정
Vector3 velocity = force / bird.mass;
for (int i = 0; i < maxStep; i++)
{
float timeElapsed = timeStep * i;
Vector3 gravity = Physics.gravity;
Vector3 trajectoryPoint = position +
velocity * timeElapsed +
gravity * (0.5f * timeElapsed * timeElapsed);
var trajectoryObject = Instantiate(trajectory, trajectoryPoint, Quaternion.identity);
trajectoryObjects.Add(trajectoryObject);
}
}
카메라 이동 구현
Bird.cs에 코드 추가
>> 카메라 추가 및 새의 위치에 따른 카메라 이동
using System;
using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;
public class Bird : MonoBehaviour
{
private Rigidbody2D _rigidbody;
private Camera mainCamera;
private void Awake()
{
_rigidbody = GetComponent<Rigidbody2D>();
mainCamera = Camera.main;
}
private void OnCollisionEnter2D(Collision2D other)
{
if (_rigidbody != null)
{
_rigidbody.drag = 1.0f;
}
Destroy(gameObject, 3.0f);
}
private void LateUpdate() // Bird가 날아갈 때 카메라 이동
{
if (transform.position.x > mainCamera.transform.position.x)
{
var vector3 = mainCamera.transform.position;
vector3.x = transform.position.x;
mainCamera.transform.position = vector3;
}
}
private void OnDestroy() // Bird가 사라지면 다시 카메라 원위치
{
if (!mainCamera.IsUnityNull())
mainCamera.GetComponent<ReturnToPosition>().StartReturnToPosition();
// Destroy할 때, UnityEngine에서는 null이지만 System에서는 null이 아니게 되는 Fake null 현상을 대비
}
}
>> 카메라 이동 구현
: ReturnToPosition.cs 를 만들어서 MainCamera에 추가
using System;
using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;
public class ReturnToPosition : MonoBehaviour
{
[SerializeField] private float returnTime;
private Vector3 startPosition;
void Start()
{
startPosition = transform.position; // 처음 카메라 위치 저장
}
public void StartReturnToPosition()
{
StartCoroutine(ReturnToPositionCoroutine());
}
IEnumerator ReturnToPositionCoroutine()
{
float duration = 0.0f;
Vector3 initPosition = transform.position; // 이동한 카메라 위치 저장
while (true)
{
float lerp = Mathf.Min(duration, returnTime) / returnTime; // duration 값을 0~1로 보간
// Mathf.Min(a, b) : a와 b 중 더 작은 값 반환
Vector3 newPos = Vector3.Slerp(initPosition, startPosition, lerp); // Slerp : 구면 선형 보간
// 이동한 카메라 위치로부터 처음 카메라 위치까지 부드럽게 보간
transform.position = newPos; // 보간한 위치로 이동
if (lerp >= 1.0f) // lerp가 1이면 처음 위치로 이동을 완료한 것이니 반복 탈출
break;
duration += Time.deltaTime;
yield return new LateUpdate(); // LateUpdate까지 정지 후 재개
}
transform.position = startPosition;
// Slerp를 하면 미세한 오차(ex. 1.00001)가 발생할 수 있으므로 다시 startPosition으로 위치 재설정
}
}
'Development > C#' 카테고리의 다른 글
멋쟁이사자처럼부트캠프 Unity 게임 개발 3기 30일차 (0) | 2025.01.11 |
---|---|
멋쟁이사자처럼부트캠프 Unity 게임 개발 3기 27일차 (0) | 2024.12.27 |
[멋쟁이사자처럼 부트캠프 TIL 회고] Unity 게임 개발 3기 18일차 (0) | 2024.12.19 |
[멋쟁이사자처럼 부트캠프 TIL 회고] Unity 게임 개발 3기 17일차 (1) | 2024.12.13 |
[멋쟁이사자처럼 부트캠프 TIL 회고] Unity 게임 개발 3기 16일차 (0) | 2024.12.11 |