[Update] 게임형식 및 오류수정
1. 게임형태 변경 - Game스텝에서 기존 1단계, 2단계 수정(회전만 가능하게). - ShootButton을 만들어 플레이어도 총알을 쏠수 있도록 수정. - Bullet, BulletSpawner, PlayerController를 수정 - SpawnZone을 생성하여 기존 고정이던 스포너를 랜덤으로 생성. 2. 오류 수정 - 모바일 버전 시 플레이어가 한방향만 보던 형상 수정. - 펜스에서 플레이어 캐릭터가 닿으면 회전하던 형상 수정.
This commit is contained in:
+29
-29
@@ -4,11 +4,16 @@ public class Bullet : MonoBehaviour
|
||||
{
|
||||
public float speed = 8f;
|
||||
private Rigidbody rb;
|
||||
|
||||
public GameObject effect;
|
||||
|
||||
public AudioSource audioSource;
|
||||
public AudioClip clip;
|
||||
public bool isPlayerBullet = false;
|
||||
|
||||
void Start()
|
||||
{
|
||||
rb = GetComponent<Rigidbody>();
|
||||
rb.linearVelocity = transform.forward * speed;
|
||||
Destroy(gameObject, 3f);
|
||||
}
|
||||
|
||||
private void OnTriggerEnter(Collider other)
|
||||
{
|
||||
@@ -19,33 +24,28 @@ public class Bullet : MonoBehaviour
|
||||
|
||||
if (other.CompareTag("Player"))
|
||||
{
|
||||
Instantiate(effect, other.transform.position, Quaternion.identity);
|
||||
|
||||
PlayerController pc = other.GetComponent<PlayerController>();
|
||||
if (pc != null)
|
||||
if (!isPlayerBullet)
|
||||
{
|
||||
pc.Die();
|
||||
GameObject.Find("The_Lead_Hits_Deep").GetComponent<AudioSource>().Stop();
|
||||
Instantiate(effect, other.transform.position, Quaternion.identity);
|
||||
PlayerController pc = other.GetComponent<PlayerController>();
|
||||
if (pc != null)
|
||||
{
|
||||
pc.Die();
|
||||
GameManager.instance.PlayDeathMusic();
|
||||
}
|
||||
Destroy(gameObject);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (other.CompareTag("Spawner"))
|
||||
{
|
||||
if (isPlayerBullet)
|
||||
{
|
||||
Destroy(other.gameObject);
|
||||
Destroy(gameObject);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Start is called once before the first execution of Update after the MonoBehaviour is created
|
||||
void Start()
|
||||
{
|
||||
rb = GetComponent<Rigidbody>();
|
||||
rb.linearVelocity = transform.forward * speed;
|
||||
|
||||
Destroy(gameObject, 3f);
|
||||
}
|
||||
|
||||
// Update is called once per frame
|
||||
void Update()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -17,26 +17,38 @@ public class BulletSpawner : MonoBehaviour
|
||||
float rate;
|
||||
float time;
|
||||
|
||||
// Start is called once before the first execution of Update after the MonoBehaviour is created
|
||||
void Start()
|
||||
{
|
||||
time = 0f;
|
||||
rate = Random.Range(min, max);
|
||||
|
||||
target = FindFirstObjectByType<PlayerController>().transform;
|
||||
PlayerController player = FindFirstObjectByType<PlayerController>();
|
||||
|
||||
if (player != null)
|
||||
{
|
||||
target = player.transform;
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError("BulletSpawner: 플레이어를 찾을 수 없습니다! 씬에 PlayerController가 있는지 확인하세요.");
|
||||
}
|
||||
|
||||
if (GameManager.instance != null)
|
||||
{
|
||||
GameManager.instance.RegisterSpawner(this);
|
||||
}
|
||||
}
|
||||
|
||||
// Update is called once per frame
|
||||
void Update()
|
||||
{
|
||||
time += Time.deltaTime;
|
||||
if (target == null) return;
|
||||
|
||||
time += Time.deltaTime;
|
||||
transform.LookAt(target);
|
||||
|
||||
if(time >= rate)
|
||||
if (time >= rate)
|
||||
{
|
||||
time = 0f;
|
||||
|
||||
rate = Random.Range(min, max);
|
||||
|
||||
GameObject obj = Instantiate(prefab, firePoint.transform.position, firePoint.transform.rotation);
|
||||
@@ -46,6 +58,20 @@ public class BulletSpawner : MonoBehaviour
|
||||
if (bulletScript != null)
|
||||
{
|
||||
bulletScript.speed = bulletSpeed;
|
||||
bulletScript.isPlayerBullet = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OnDestroy()
|
||||
{
|
||||
if (GameManager.instance != null)
|
||||
{
|
||||
GameManager.instance.UnregisterSpawner(this);
|
||||
|
||||
if (!GameManager.instance.isGameover)
|
||||
{
|
||||
GameManager.instance.RequestRespawn();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+107
-20
@@ -1,4 +1,6 @@
|
||||
using NUnit.Framework.Constraints;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
using UnityEngine.UI;
|
||||
@@ -11,36 +13,41 @@ public class GameManager : MonoBehaviour
|
||||
public Text recordText;
|
||||
|
||||
private float surviveTime;
|
||||
private bool isGameover;
|
||||
public bool isGameover;
|
||||
|
||||
public GameObject restartButton;
|
||||
|
||||
public void EndGame()
|
||||
public static GameManager instance;
|
||||
|
||||
public AudioSource leadAudio;
|
||||
public AudioSource deathAudio;
|
||||
|
||||
public List<BulletSpawner> activeSpawners = new List<BulletSpawner>();
|
||||
public Transform player;
|
||||
public SpawnZone spawnZone;
|
||||
public GameObject spawnerPrefab;
|
||||
|
||||
public void RegisterSpawner(BulletSpawner s) => activeSpawners.Add(s);
|
||||
public void UnregisterSpawner(BulletSpawner s) => activeSpawners.Remove(s);
|
||||
|
||||
public int maxSpawnerCount = 2;
|
||||
|
||||
public Transform rotationPlate;
|
||||
|
||||
void Awake()
|
||||
{
|
||||
isGameover = true;
|
||||
gameoverText.SetActive(true);
|
||||
restartButton.SetActive(true);
|
||||
|
||||
float bestTime = PlayerPrefs.GetFloat("BestTime");
|
||||
if(surviveTime > bestTime)
|
||||
{
|
||||
bestTime = surviveTime;
|
||||
PlayerPrefs.SetFloat("BestTime", bestTime);
|
||||
}
|
||||
|
||||
recordText.text = "Best Time: " + (int)bestTime;
|
||||
|
||||
if (instance == null) instance = this;
|
||||
}
|
||||
|
||||
|
||||
// Start is called once before the first execution of Update after the MonoBehaviour is created
|
||||
void Start()
|
||||
{
|
||||
surviveTime = 0;
|
||||
isGameover = false;
|
||||
|
||||
if (leadAudio != null) leadAudio.Play();
|
||||
if (deathAudio != null) deathAudio.Stop();
|
||||
}
|
||||
|
||||
// Update is called once per frame
|
||||
void Update()
|
||||
{
|
||||
if(!isGameover)
|
||||
@@ -50,12 +57,10 @@ public class GameManager : MonoBehaviour
|
||||
}
|
||||
else
|
||||
{
|
||||
// 1. PC: R키
|
||||
if (Input.GetKeyDown(KeyCode.R))
|
||||
{
|
||||
RestartGame();
|
||||
}
|
||||
// 2. 모바일/PC: 클릭 또는 터치 (화면 아무데나 눌러도 재시작)
|
||||
if (Input.GetMouseButtonDown(0))
|
||||
{
|
||||
RestartGame();
|
||||
@@ -73,4 +78,86 @@ public class GameManager : MonoBehaviour
|
||||
{
|
||||
UnityEngine.SceneManagement.SceneManager.LoadScene(1);
|
||||
}
|
||||
|
||||
public void PlayDeathMusic()
|
||||
{
|
||||
if (leadAudio != null) leadAudio.Stop();
|
||||
if (deathAudio != null) deathAudio.Play();
|
||||
}
|
||||
|
||||
public void EndGame()
|
||||
{
|
||||
isGameover = true;
|
||||
gameoverText.SetActive(true);
|
||||
restartButton.SetActive(true);
|
||||
|
||||
float bestTime = PlayerPrefs.GetFloat("BestTime");
|
||||
if (surviveTime > bestTime)
|
||||
{
|
||||
bestTime = surviveTime;
|
||||
PlayerPrefs.SetFloat("BestTime", bestTime);
|
||||
}
|
||||
|
||||
recordText.text = "Best Time: " + (int)bestTime;
|
||||
|
||||
}
|
||||
|
||||
public Vector3 GetValidSpawnPosition()
|
||||
{
|
||||
int maxAttempts = 10;
|
||||
for (int i = 0; i < maxAttempts; i++)
|
||||
{
|
||||
Vector3 candidate = spawnZone.GetRandomPosition();
|
||||
|
||||
|
||||
if (Vector3.Distance(candidate, player.position) < 5f) continue;
|
||||
|
||||
bool isOverlap = false;
|
||||
foreach (var spawner in activeSpawners)
|
||||
{
|
||||
if (Vector3.Distance(candidate, spawner.transform.position) < 3f)
|
||||
{
|
||||
isOverlap = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!isOverlap) return candidate;
|
||||
}
|
||||
return spawnZone.GetRandomPosition();
|
||||
}
|
||||
|
||||
public void RequestRespawn()
|
||||
{
|
||||
StartCoroutine(RespawnRoutine());
|
||||
}
|
||||
|
||||
IEnumerator RespawnRoutine()
|
||||
{
|
||||
yield return new WaitForSeconds(3f);
|
||||
|
||||
Vector3 validPos = GetValidSpawnPosition();
|
||||
|
||||
GameObject newSpawner = Instantiate(spawnerPrefab, validPos, Quaternion.identity);
|
||||
|
||||
if (rotationPlate != null)
|
||||
{
|
||||
newSpawner.transform.SetParent(rotationPlate);
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateMaxSpawnerCount(int newCount)
|
||||
{
|
||||
maxSpawnerCount = newCount;
|
||||
|
||||
int currentCount = activeSpawners.Count;
|
||||
if (currentCount < maxSpawnerCount)
|
||||
{
|
||||
int needed = maxSpawnerCount - currentCount;
|
||||
for (int i = 0; i < needed; i++)
|
||||
{
|
||||
RequestRespawn();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+24
-43
@@ -2,17 +2,21 @@ using UnityEngine;
|
||||
|
||||
public class NewMonoBehaviourScript : MonoBehaviour
|
||||
{
|
||||
public GameObject[] spawners;
|
||||
public Rotator rotator;
|
||||
|
||||
private GameManager gameManager;
|
||||
private int currentStep = 0;
|
||||
|
||||
private int lastMaxCount = 2;
|
||||
private int lastStep = -1;
|
||||
|
||||
void Start()
|
||||
{
|
||||
gameManager = FindFirstObjectByType<GameManager>();
|
||||
|
||||
InitializeDifficulty();
|
||||
gameManager.UpdateMaxSpawnerCount(2);
|
||||
|
||||
UpdateStep(0);
|
||||
}
|
||||
|
||||
void Update()
|
||||
@@ -20,71 +24,48 @@ public class NewMonoBehaviourScript : MonoBehaviour
|
||||
if (gameManager == null) return;
|
||||
|
||||
float currentTime = gameManager.GetSurviveTime();
|
||||
int targetStep = 1;
|
||||
|
||||
if (currentTime > 30f) targetStep = 4;
|
||||
else if (currentTime > 20f) targetStep = 3;
|
||||
else if (currentTime > 10f) targetStep = 2;
|
||||
else targetStep = 1;
|
||||
int targetMax = 2;
|
||||
|
||||
if (currentStep != targetStep)
|
||||
if (currentTime > 10f)
|
||||
{
|
||||
UpdateStep(targetStep);
|
||||
targetMax = 2 + Mathf.FloorToInt((currentTime - 10f) / 4f);
|
||||
}
|
||||
}
|
||||
|
||||
if(targetMax != lastMaxCount)
|
||||
{
|
||||
lastMaxCount = targetMax;
|
||||
gameManager.UpdateMaxSpawnerCount(targetMax);
|
||||
}
|
||||
|
||||
void InitializeDifficulty()
|
||||
{
|
||||
foreach (var s in spawners) s.SetActive(false);
|
||||
if (rotator != null) rotator.enabled = false;
|
||||
|
||||
UpdateStep(1);
|
||||
int currentStep = (int)currentTime / 10;
|
||||
if (currentStep != lastStep)
|
||||
{
|
||||
lastStep = currentStep;
|
||||
UpdateStep(currentStep);
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateStep(int step)
|
||||
{
|
||||
currentStep = step;
|
||||
switch (step)
|
||||
{
|
||||
case 0:
|
||||
case 1:
|
||||
SetSpawnersActive(2);
|
||||
if (rotator != null) rotator.enabled = false;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
SetSpawnersActive(4);
|
||||
if (rotator != null) rotator.enabled = false;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
SetSpawnersActive(4);
|
||||
if (rotator != null) rotator.enabled = true;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
SetSpawnersActive(4);
|
||||
if (rotator != null) rotator.enabled = true;
|
||||
UpgradeBullSpeed(12f);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void SetSpawnersActive(int count)
|
||||
{
|
||||
for(int i = 0; i < spawners.Length; i++)
|
||||
{
|
||||
spawners[i].SetActive(i < count);
|
||||
}
|
||||
}
|
||||
|
||||
void UpgradeBullSpeed(float newSpeed)
|
||||
{
|
||||
foreach (var obj in spawners)
|
||||
{
|
||||
if (obj == null) continue;
|
||||
BulletSpawner spawner = obj.GetComponent<BulletSpawner>();
|
||||
if (spawner != null) spawner.bulletSpeed = newSpeed;
|
||||
default:
|
||||
if (rotator != null) rotator.enabled = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,16 +2,16 @@ using UnityEngine;
|
||||
|
||||
public class PlatformUIHandler : MonoBehaviour
|
||||
{
|
||||
public GameObject joystickUI; // 모바일 조이스틱 오브젝트
|
||||
public GameObject buttonUI; // 가상 버튼 오브젝트
|
||||
public GameObject joystickUI;
|
||||
public GameObject buttonUI;
|
||||
public GameObject shootButtonUI;
|
||||
|
||||
void Start()
|
||||
{
|
||||
// 아까 Intro에서 저장한 값을 확인
|
||||
bool isMobile = GameSettings.IsMobile;
|
||||
|
||||
// 모바일이면 켜고, 아니면 끔
|
||||
if (joystickUI != null) joystickUI.SetActive(isMobile);
|
||||
if (buttonUI != null) buttonUI.SetActive(isMobile);
|
||||
if (shootButtonUI != null) shootButtonUI.SetActive(isMobile);
|
||||
}
|
||||
}
|
||||
@@ -12,13 +12,28 @@ public class PlayerController : MonoBehaviour
|
||||
public int shieldCount = 3;
|
||||
private bool isShieldActive = false;
|
||||
public GameObject shieldVisual;
|
||||
public ShieldUIHandler shieldUI; // UI 전용 스크립트 참조
|
||||
public ShieldUIHandler shieldUI;
|
||||
|
||||
[Header("Shooting")]
|
||||
public GameObject bulletPrefab;
|
||||
public Transform firePoint;
|
||||
public int maxAmmo = 6;
|
||||
public float reloadTime = 1.5f;
|
||||
|
||||
private int currentAmmo;
|
||||
private bool isReloading = false;
|
||||
|
||||
public ShootButtonUI shootButtonUI;
|
||||
|
||||
private Vector3 lastMoveDirection = Vector3.forward;
|
||||
|
||||
void Start()
|
||||
{
|
||||
playerRigidbody = GetComponent<Rigidbody>();
|
||||
|
||||
// 초기 UI 상태 반영
|
||||
currentAmmo = maxAmmo;
|
||||
if (shootButtonUI != null) shootButtonUI.UpdateAmmoUI(currentAmmo, maxAmmo);
|
||||
|
||||
if (shieldUI != null) shieldUI.UpdateShieldUI(shieldCount);
|
||||
}
|
||||
|
||||
@@ -26,11 +41,15 @@ public class PlayerController : MonoBehaviour
|
||||
{
|
||||
HandleMovement();
|
||||
|
||||
// PC 입력 처리 (모바일 아닐 때만)
|
||||
if (!GameSettings.IsMobile && Input.GetKeyDown(KeyCode.Alpha1))
|
||||
{
|
||||
ActivateShieldLogic();
|
||||
}
|
||||
|
||||
if (!GameSettings.IsMobile && Input.GetKeyDown(KeyCode.Space))
|
||||
{
|
||||
Shoot();
|
||||
}
|
||||
}
|
||||
|
||||
void HandleMovement()
|
||||
@@ -40,7 +59,8 @@ public class PlayerController : MonoBehaviour
|
||||
if (GameSettings.IsMobile && joystick != null)
|
||||
{
|
||||
Vector2 input = joystick.GetInput();
|
||||
x = input.x; z = input.y;
|
||||
x = input.x;
|
||||
z = input.y;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -48,16 +68,16 @@ public class PlayerController : MonoBehaviour
|
||||
z = Input.GetAxis("Vertical");
|
||||
}
|
||||
|
||||
playerRigidbody.linearVelocity = new Vector3(x * speed, 0f, z * speed);
|
||||
playerRigidbody.linearVelocity = new Vector3(x * speed, playerRigidbody.linearVelocity.y, z * speed);
|
||||
|
||||
if (x != 0 || z != 0)
|
||||
if (Mathf.Abs(x) > 0.1f || Mathf.Abs(z) > 0.1f)
|
||||
{
|
||||
transform.rotation = Quaternion.LookRotation(new Vector3(x, 0f, z));
|
||||
lastMoveDirection = new Vector3(x, 0, z).normalized;
|
||||
}
|
||||
|
||||
// 애니메이션
|
||||
|
||||
Animator anim = GetComponentInChildren<Animator>();
|
||||
if (anim != null) anim.SetBool("isMoving", (x != 0 || z != 0));
|
||||
if (anim != null) anim.SetBool("isMoving", (Mathf.Abs(x) > 0.1f || Mathf.Abs(z) > 0.1f));
|
||||
}
|
||||
|
||||
public void ActivateShieldLogic()
|
||||
@@ -73,7 +93,6 @@ public class PlayerController : MonoBehaviour
|
||||
isShieldActive = true;
|
||||
shieldCount--;
|
||||
|
||||
// UI 업데이트 위임
|
||||
if (shieldUI != null) shieldUI.UpdateShieldUI(shieldCount);
|
||||
|
||||
if (shieldVisual != null) shieldVisual.SetActive(true);
|
||||
@@ -88,4 +107,76 @@ public class PlayerController : MonoBehaviour
|
||||
gameObject.SetActive(false);
|
||||
FindFirstObjectByType<GameManager>()?.EndGame();
|
||||
}
|
||||
|
||||
public void Shoot(Vector2? inputDirection = null)
|
||||
{
|
||||
// 리로드 중이거나 탄이 없으면 발사 불가
|
||||
if (isReloading || currentAmmo <= 0)
|
||||
return;
|
||||
|
||||
if (bulletPrefab == null || firePoint == null)
|
||||
return;
|
||||
|
||||
// 탄 차감
|
||||
currentAmmo--;
|
||||
if (shootButtonUI != null) shootButtonUI.UpdateAmmoUI(currentAmmo, maxAmmo);
|
||||
|
||||
// 방향 결정
|
||||
Vector3 lookDir;
|
||||
if (inputDirection.HasValue && inputDirection.Value.magnitude > 0.1f)
|
||||
{
|
||||
lookDir = new Vector3(inputDirection.Value.x, 0, inputDirection.Value.y).normalized;
|
||||
lastMoveDirection = lookDir;
|
||||
}
|
||||
else
|
||||
{
|
||||
lookDir = lastMoveDirection;
|
||||
}
|
||||
|
||||
Quaternion bulletRotation = Quaternion.LookRotation(lookDir);
|
||||
GameObject bullet = Instantiate(bulletPrefab, firePoint.position, bulletRotation);
|
||||
bullet.transform.forward = lookDir;
|
||||
|
||||
Bullet bulletScript = bullet.GetComponent<Bullet>();
|
||||
if (bulletScript != null)
|
||||
{
|
||||
bulletScript.isPlayerBullet = true;
|
||||
bulletScript.speed = 8f;
|
||||
}
|
||||
|
||||
Collider bulletCollider = bullet.GetComponent<Collider>();
|
||||
Collider playerCollider = GetComponent<Collider>();
|
||||
if (bulletCollider != null && playerCollider != null)
|
||||
{
|
||||
Physics.IgnoreCollision(bulletCollider, playerCollider);
|
||||
}
|
||||
|
||||
// 마지막 탄을 쐈으면 자동 리로드 시작
|
||||
if (currentAmmo <= 0)
|
||||
{
|
||||
StartCoroutine(ReloadRoutine());
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerator ReloadRoutine()
|
||||
{
|
||||
isReloading = true;
|
||||
if (shootButtonUI != null) shootButtonUI.SetReloading(true);
|
||||
|
||||
yield return new WaitForSeconds(reloadTime);
|
||||
|
||||
currentAmmo = maxAmmo;
|
||||
isReloading = false;
|
||||
|
||||
if (shootButtonUI != null)
|
||||
{
|
||||
shootButtonUI.SetReloading(false);
|
||||
shootButtonUI.UpdateAmmoUI(currentAmmo, maxAmmo);
|
||||
}
|
||||
}
|
||||
|
||||
void LateUpdate()
|
||||
{
|
||||
transform.rotation = Quaternion.LookRotation(lastMoveDirection);
|
||||
}
|
||||
}
|
||||
@@ -3,12 +3,10 @@ using TMPro;
|
||||
|
||||
public class RestartTextHandler : MonoBehaviour
|
||||
{
|
||||
// [SerializeField]를 쓰면 private이어도 인스펙터 창에 뜹니다!
|
||||
[SerializeField] private TextMeshProUGUI restartText;
|
||||
|
||||
void OnEnable()
|
||||
{
|
||||
// 이제 null 체크를 할 필요도 거의 없습니다. (인스펙터에서 넣을 거니까요)
|
||||
if (restartText == null)
|
||||
{
|
||||
Debug.LogError("인스펙터에 텍스트 오브젝트를 할당해주세요!");
|
||||
|
||||
@@ -8,15 +8,5 @@ public class SceneChange : MonoBehaviour
|
||||
{
|
||||
SceneManager.LoadScene("Game");
|
||||
}
|
||||
// Start is called once before the first execution of Update after the MonoBehaviour is created
|
||||
void Start()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// Update is called once per frame
|
||||
void Update()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,8 +3,8 @@ using UnityEngine.UI;
|
||||
|
||||
public class ShieldRelocator : MonoBehaviour
|
||||
{
|
||||
public Transform pcAnchor; // PC 화면 위치
|
||||
public Transform mobileAnchor; // 모바일 버튼 내부 위치
|
||||
public Transform pcAnchor;
|
||||
public Transform mobileAnchor;
|
||||
|
||||
void Awake()
|
||||
{
|
||||
|
||||
@@ -7,19 +7,16 @@ public class ShieldUIHandler : MonoBehaviour
|
||||
[SerializeField] private Image shieldIcon;
|
||||
[SerializeField] private TextMeshProUGUI countText;
|
||||
|
||||
// UI 업데이트만 담당하는 함수
|
||||
public void UpdateShieldUI(int count)
|
||||
{
|
||||
if (countText != null)
|
||||
{
|
||||
countText.text = count.ToString();
|
||||
// 개수가 0이면 텍스트 숨기기
|
||||
countText.gameObject.SetActive(count > 0);
|
||||
}
|
||||
|
||||
if (shieldIcon != null)
|
||||
{
|
||||
// 색상 조절 로직
|
||||
shieldIcon.color = (count > 0) ? Color.white : new Color(0.2f, 0.2f, 0.2f, 0.5f);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
|
||||
public class ShootButton : MonoBehaviour, IPointerDownHandler, IPointerUpHandler
|
||||
{
|
||||
[SerializeField] private float rotationLimit = 40;
|
||||
[SerializeField] private float rotationSpeed = 15;
|
||||
private bool rotate = false;
|
||||
private bool isDisabled = false;
|
||||
|
||||
public PlayerController playerController;
|
||||
|
||||
void FixedUpdate()
|
||||
{
|
||||
float targetRotate = rotate ? rotationLimit : 0f;
|
||||
Quaternion target = Quaternion.Euler(targetRotate, 0, 0);
|
||||
transform.rotation = Quaternion.Slerp(transform.rotation, target, Time.deltaTime * rotationSpeed);
|
||||
}
|
||||
|
||||
public void OnPointerDown(PointerEventData pointerEventData)
|
||||
{
|
||||
if (isDisabled) return;
|
||||
|
||||
rotate = true;
|
||||
|
||||
if (playerController != null)
|
||||
{
|
||||
Vector2? input = (GameSettings.IsMobile && playerController.joystick != null)
|
||||
? playerController.joystick.GetInput()
|
||||
: null;
|
||||
|
||||
playerController.Shoot(input);
|
||||
}
|
||||
}
|
||||
|
||||
public void OnPointerUp(PointerEventData pointerEventData)
|
||||
{
|
||||
rotate = false;
|
||||
}
|
||||
|
||||
// 외부에서 호출
|
||||
public void SetDisabled(bool disabled)
|
||||
{
|
||||
isDisabled = disabled;
|
||||
if (disabled) rotate = false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4de305db8999c874386cdb0baaa3eb61
|
||||
@@ -0,0 +1,42 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using TMPro;
|
||||
|
||||
public class ShootButtonUI : MonoBehaviour
|
||||
{
|
||||
[Header("References")]
|
||||
public TMP_Text ammoText;
|
||||
|
||||
private ShootButton shootButton;
|
||||
private int lastCurrent;
|
||||
private int lastMax;
|
||||
|
||||
void Awake()
|
||||
{
|
||||
shootButton = GetComponent<ShootButton>();
|
||||
}
|
||||
|
||||
public void UpdateAmmoUI(int current, int max)
|
||||
{
|
||||
lastCurrent = current;
|
||||
lastMax = max;
|
||||
|
||||
if (ammoText != null)
|
||||
ammoText.text = $"{current}/{max}";
|
||||
}
|
||||
|
||||
public void SetReloading(bool reloading)
|
||||
{
|
||||
if (ammoText != null)
|
||||
{
|
||||
if (reloading)
|
||||
ammoText.text = "Reload";
|
||||
else
|
||||
ammoText.text = $"{lastCurrent}/{lastMax}";
|
||||
}
|
||||
|
||||
// 버튼 입력 차단/해제
|
||||
if (shootButton != null)
|
||||
shootButton.SetDisabled(reloading);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5179a74c586a0c242bff159b71c9b794
|
||||
@@ -0,0 +1,16 @@
|
||||
using UnityEngine;
|
||||
|
||||
public class SpawnZone : MonoBehaviour
|
||||
{
|
||||
public BoxCollider area;
|
||||
|
||||
public Vector3 GetRandomPosition()
|
||||
{
|
||||
Bounds bounds = area.bounds;
|
||||
return new Vector3(
|
||||
Random.Range(bounds.min.x, bounds.max.x),
|
||||
bounds.center.y,
|
||||
Random.Range(bounds.min.z, bounds.max.z)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 28cbeb060fae10746bedde0296e2585c
|
||||
Reference in New Issue
Block a user