반응형
목표 |
플레이어 를 태그로 찾아서 그 위치로 이동하는 부분을 구현해 보자.
실습 |
플레이어에 태그를 Player 로 선택하자.
2022.06.01 - [응용프로그래밍/유니티기초] - [유니티기초]2-04. 애니메이션
애니메이션을 만들었던 orc 에 다음과 같이 스크립트를 추가하면 Player 위치를 찾아서 이동하는 것을 확인 할 수 있다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Monster : MonoBehaviour
{
GameObject player = null;
private Vector3 targetPosition;
public bool lookRight = true;
public float speed=0.5f;
private Animator animator;
// Start is called before the first frame update
void Start()
{
player = GameObject.FindWithTag("Player");
animator = GetComponent<Animator>();
}
// Update is called once per frame
void Update()
{
targetPosition = player.transform.position;
//transform.position = Vector3.MoveTowards(gameObject.transform.position,player.GameObject.transform,2.0f) ;
if (targetPosition.x > transform.position.x && !lookRight) //타겟이 오른쪽에 있으면서 현재 왼쪽을 바라 보고 있으면 방향 회전
Flip();
if(targetPosition.x < transform.position.x && lookRight)
Flip();
var p = transform.position;
transform.position = Vector3.MoveTowards(transform.position, targetPosition, speed * Time.deltaTime);
//Vector3 vel = targetPosition - transform.position;
//vel = Vector3.ClampMagnitude(vel, speed * Time.deltaTime);
//transform.position += vel;
animator.SetFloat("speed", (transform.position - p).magnitude/Time.deltaTime);
}
public void Flip()
{
var s = transform.localScale;
s.x *= -1;
transform.localScale = s;
lookRight = !lookRight;
}
}
태그 이름으로 객채를 찾는 것은 GameObject.FindWithTag("Player");
Flip() 에서는 localScale 의 x축을 이용하여 좌우를 반전 하도록 처리했다.
animator 의 speed 값을 주어서 walk 애니메이션을 동작하도록 처리했다.
Vector3.MoveTowards 로 타겟 위치로 speed 속도로 이동하도록 처리했다.
전체 코드
-Dragon.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Dragon : MonoBehaviour,IMonster
{
public void Fly()
{
Debug.Log("날기");
}
public void Attack(){
Debug.Log("Dragon이 공격을 합니다.");
}
public void Say(){
Debug.Log("Dragon이 말을 합니다.");
}
}
- GameManager.cs
using UnityEngine;
using UnityEngine.SceneManagement;
// 점수와 게임 오버 여부를 관리하는 게임 매니저
public class GameManager : MonoBehaviour {
// 외부에서 싱글톤 오브젝트를 가져올때 사용할 프로퍼티
public static GameManager instance
{
get
{
// 만약 싱글톤 변수에 아직 오브젝트가 할당되지 않았다면
if (m_instance == null)
{
// 씬에서 GameManager 오브젝트를 찾아 할당
m_instance = FindObjectOfType<GameManager>();
}
// 싱글톤 오브젝트를 반환
return m_instance;
}
}
private static GameManager m_instance; // 싱글톤이 할당될 static 변수
private int score = 0; // 현재 게임 점수
public bool isGameover { get; private set; } // 게임 오버 상태
private void Awake() {
// 씬에 싱글톤 오브젝트가 된 다른 GameManager 오브젝트가 있다면
if (instance != this)
{
// 자신을 파괴
Destroy(gameObject);
}
}
private void Start() {
FindObjectOfType<PlayerMovement>().onDeath += EndGame;
}
// 점수를 추가하고 UI 갱신
public void AddScore(int newScore) {
// 게임 오버가 아닌 상태에서만 점수 증가 가능
if (!isGameover)
{
// 점수 추가
score += newScore;
// 점수 UI 텍스트 갱신
UIManager.instance.UpdateScoreText(score);
}
}
// 게임 오버 처리
public void EndGame() {
// 게임 오버 상태를 참으로 변경
isGameover = true;
// 게임 오버 UI를 활성화
UIManager.instance.SetActiveGameoverUI(true);
}
private void Update() {
}
}
- IMonster.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public interface IMonster
{
public void Attack();
public void Say(); //여기서는 정의만 한다.
}
- Monster.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Monster : MonoBehaviour
{
GameObject player = null;
private Vector3 targetPosition;
public bool lookRight = true;
public float speed=0.5f;
private Animator animator;
private float atackDelay = 0;
private bool Attack = false;
// Start is called before the first frame update
void Start()
{
player = GameObject.FindWithTag("Player");
animator = GetComponent<Animator>();
}
// Update is called once per frame
void Update()
{
if(!Attack){
targetPosition = player.transform.position;
//transform.position = Vector3.MoveTowards(gameObject.transform.position,player.GameObject.transform,2.0f) ;
if (targetPosition.x > transform.position.x && !lookRight) //타겟이 오른쪽에 있으면서 현재 왼쪽을 바라 보고 있으면 방향 회전
Flip();
if(targetPosition.x < transform.position.x && lookRight)
Flip();
var p = transform.position;
transform.position = Vector3.MoveTowards(transform.position, targetPosition, speed * Time.deltaTime);
//Vector3 vel = targetPosition - transform.position;
//vel = Vector3.ClampMagnitude(vel, speed * Time.deltaTime);
//transform.position += vel;
animator.SetFloat("speed", (transform.position - p).magnitude/Time.deltaTime);
}
else {
atackDelay+=Time.deltaTime;
if(atackDelay<1) return;
atackDelay=0;
animator.SetTrigger("attack");
Attack=false;
}
}
public void Flip()
{
var s = transform.localScale;
s.x *= -1;
transform.localScale = s;
lookRight = !lookRight;
}
private void OnCollisionEnter2D(Collision2D other) {
if(other.gameObject.tag=="Player"){
Attack = true;
atackDelay = 0f;
//animator.SetTrigger("attack");
Debug.Log("OnCollisionEnter2D");
}
}
private void OnCollOnCollisionExit2D(Collision2D other) {
if(other.gameObject.tag=="Player"){
Attack = false;
//animator.SetTrigger("attack");
Debug.Log("OnCollOnCollisionExit2D");
}
}
}
- ObjectSpawner.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ObjectSpawner : MonoBehaviour
{
public GameObject circle;
public Transform FirePos;
// Start is called before the first frame update
Rigidbody2D rb; //Rigidbody 를 연결할 변수 선언
public float speed = 5.0f; // 이동 속도
Vector3 dir;
private void Awake() {
//Quaternion.identity 회전값(0,0,0)
/*Quaternion rotation = Quaternion.Euler(0,0,0); //각도를 나타내는 오일러를 Quaternion 으로 변환
c1.name = "동그라미1";
c1.GetComponent<SpriteRenderer>().color = Color.yellow; //생성된 객체 색상 변경
c1.transform.position = new Vector3(-3,3,0); //생성된 객체 위치 변경
c1.transform.localScale = new Vector3(0.5f,0.5f,0); //생성된 객체 크기 변경
Destroy(c1,3f);
*/
/*
for(int y=0;y<10;y++){
for(int x=0;x<10;x++){
Vector3 position = new Vector3(-4.5f + x,-4.5f + y,0);
Instantiate(circle,position,Quaternion.identity);
}
}
*/
}
void Start()
{
rb = GetComponent<Rigidbody2D>(); //자신의 Rigidbody 를 가져와서 rb에 연결
dir = Vector3.right;
}
// Update is called once per frame
void Update()
{
}
}
- Orc.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Orc : MonoBehaviour,IMonster
{
public void WarCry()
{
Debug.Log("전투함성");
}
public void Attack(){
Debug.Log("Orc가 공격을 합니다.");
}
public void Say(){
Debug.Log("Orc가 말을 합니다.");
}
public void Update(){
}
}
- PlayerInput.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerInput : MonoBehaviour
{
public string moveAxisName = "Vertical"; // 앞뒤 움직임을 위한 입력축 이름
public string rotateAxisName = "Horizontal"; // 좌우 회전을 위한 입력축 이름
public string fireButtonName = "Fire1"; // 발사를 위한 입력 버튼 이름
public string jumpButtonName = "Jump"; // 점프를 위한 입력 버튼 이름
// 값 할당은 내부에서만 가능
public float move { get; private set; } // 감지된 움직임 입력값
public float rotate { get; private set; } // 감지된 회전 입력값
public bool fire { get; private set; } // 감지된 발사 입력값
public float jump { get; private set; } // 감지된 점프 입력값
// 매프레임 사용자 입력을 감지
private void Update() {
// 게임오버 상태에서는 사용자 입력을 감지하지 않는다
if (GameManager.instance != null && GameManager.instance.isGameover)
{
move = 0;
rotate = 0;
fire = false;
jump = 0;
return;
}
// move에 관한 입력 감지
move = Input.GetAxis(moveAxisName);
// rotate에 관한 입력 감지
rotate = Input.GetAxis(rotateAxisName);
// fire에 관한 입력 감지
fire = Input.GetButton(fireButtonName);
// jump 관한 입력 감지
jump = Input.GetAxis(jumpButtonName);
}
}
- PlayerMovement.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
public class PlayerMovement : MonoBehaviour
{
private int score = 0;
public bool dead { get; protected set; } // 사망 상태
public event Action onDeath; // 사망시 발동할 이벤트
public float speed = 10f; // 이동 속도
Rigidbody2D rb;
// Start is called before the first frame update
private void Awake() {
UIManager.instance.SetActiveGameoverUI(false);
Debug.Log("PlayerMovement");
}
void Start()
{
rb = GetComponent<Rigidbody2D>();
}
// Update is called once per frame
void Update()
{
if(dead) return;
GameManager.instance.AddScore(++score);
float xInput = Input.GetAxis("Horizontal");
float zInput = Input.GetAxis("Vertical");
float yInput = Input.GetAxis("Jump");
float xSpeed = xInput * speed;
float zSpeed = zInput * speed;
float ySpeed = yInput * speed;
transform.position += new Vector3(xSpeed,ySpeed,zSpeed) * Time.deltaTime;
//UIManager.instance.UpdateScoreText(++score);
}
private void OnCollisionEnter2D(Collision2D other) {
if(other.gameObject.tag=="bottom"){
//Die();
}
IMonster monster = other.gameObject.GetComponent<IMonster>();
if(monster!=null) {
monster.Say();
Rigidbody2D otherrb = other.gameObject.GetComponent<Rigidbody2D>();
otherrb.constraints = RigidbodyConstraints2D.FreezeAll;
/*
Animator animator = other.gameObject.GetComponent<Animator>();
animator.SetTrigger("Die");
*/
}
}
// 사망 처리
public virtual void Die() {
// onDeath 이벤트에 등록된 메서드가 있다면 실행
if (onDeath != null)
{
onDeath();
}
// 사망 상태를 참으로 변경
dead = true;
}
}
- TraceScript.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TraceScript : MonoBehaviour
{
public GameObject player; //추적할 게임 오브젝트
private Transform trace; //추적할 게임 오브젝트의 transform
// Start is called before the first frame update
void Start()
{
trace = player.transform;
}
// Update is called once per frame
void Update()
{
//transform.position = new Vector3(trace.position.x,trace.position.y,-10);
transform.position = Vector3.Lerp(transform.position,new Vector3(trace.position.x,trace.position.y,-10),0.5f*Time.deltaTime);
//transform.position.z = -10;
//transform.TranslateZ(-10); //카메라를 원래 z축으로 이동
}
}
- UIManager.cs
using UnityEngine;
using UnityEngine.SceneManagement; // 씬 관리자 관련 코드
using UnityEngine.UI; // UI 관련 코드
// 필요한 UI에 즉시 접근하고 변경할 수 있도록 허용하는 UI 매니저
public class UIManager : MonoBehaviour {
// 싱글톤 접근용 프로퍼티
public static UIManager instance
{
get
{
if (m_instance == null)
{
m_instance = FindObjectOfType<UIManager>();
}
return m_instance;
}
}
private static UIManager m_instance; // 싱글톤이 할당될 변수
public Text scoreText; // 점수 표시용 텍스트
public GameObject gameoverUI; // 게임 오버시 활성화할 UI
// 점수 텍스트 갱신
public void UpdateScoreText(int newScore) {
scoreText.text = "Score : " + newScore;
}
// 게임 오버 UI 활성화
public void SetActiveGameoverUI(bool active) {
gameoverUI.SetActive(active);
}
// 게임 재시작
public void GameRestart() {
SceneManager.LoadScene(SceneManager.GetActiveScene().name);
}
}
반응형
'응용프로그래밍 > 유니티기초' 카테고리의 다른 글
[유니티2D 활용] 테트리스 게임 만들기 (0) | 2022.06.03 |
---|---|
[유니티2D활용]지뢰찾기 게임 만들기 (0) | 2022.06.01 |
[유니티기초]2-04. 애니메이션 (0) | 2022.06.01 |
[유니티기초] 2-03. 두 객체가 부딪혔을 때 밀림 방지 (0) | 2022.05.31 |
[유니티기초] 2-02. 다형성과 인터페이스 (0) | 2022.05.31 |