기본 세팅
플레이어 조이스틱으로 움직이면 - 걷는 애니메이션
떼면 idle
카메라 따라가기
using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.Animations;
public class FollowCamera : MonoBehaviour
{
public Transform targetTr;
private Transform cameraTr;
[Range(2.0f, 20.0f)]
public float distance = 8.0f;
[Range(10.0f, 20.0f)]
public float height = 15.0f;
// Start is called before the first frame update
void Start()
{
this.cameraTr = this.GetComponent<Transform>();
}
// Update is called once per frame
void LateUpdate()
{
this.cameraTr.position = new Vector3(6, height , targetTr.position.z- distance);
this.cameraTr.LookAt(targetTr.position);
this.cameraTr.rotation = Quaternion.Euler(27, 0, 0);
}
}
카메라가 회전하면 안되고 player를 따라 z 축으로만 이동해야한다.

<이동할때는 방향 쳐다보다가 멈췄을 때는 보스 바라보기>
player스크립트에 추가
[SerializeField]
private GameObject bossPrefab;
public void Idle()
{
//Debug.Log("idle");
this.anim.SetInteger("State", 0);
this.transform.LookAt(this.bossPrefab.transform.position);
//this.rBody.isKinematic = true;
}

<총알 발사 구현>
조이스틱에서 손을 떼면 총알 발사하기
코루틴으로 총알을 일정한 간격으로 연속적으로 발사 구현
=>
this.joystick1.onUp = () =>
{
this.isDown = false;
this.player.Attack();//아래에서 dir=vector3.zero 면 idle 실행하는거 썼는데 왜 여기다가 또 썼을까?
this.fireController.Fire();
};
조이스틱에서 손을 떼면 발사되도록 하는데 , 다시 조이스틱을 눌러도 계속 총알이 발사됨.
로그를 찍어보니 로그는 제대로 하나씩 찍히는데 up될때마다 코루틴이 호출되어서 총알이 두발씩 발사되고 두발 세발 .. 늘어남, ==> stopCoroutine을 사용
this.joystick1.onDown = () =>
{
this.isDown = true;
this.fireController.StopFire();
};
this.joystick1.onUp = () =>
{
this.isDown = false;
this.player.Attack();//아래에서 dir=vector3.zero 면 idle 실행하는거 썼는데 왜 여기다가 또 썼을까?
this.fireController.Fire();
};
stopCoroutine을 했는데도 결과가 똑같이 나옴
===> 찾아보니 변수를 선언해야한다고 함

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class FireController : MonoBehaviour
{
[SerializeField]
private GameObject bulletPrefab;
[SerializeField]
private Transform firePos;
private IEnumerator shootRoutine;
private void Start()
{
shootRoutine = CoFire();
}
public void Fire()
{
Debug.Log("총알발사");
this.StartCoroutine(shootRoutine);
}
public void StopFire()
{
Debug.Log("총알 발사 중지");
this.StopCoroutine(shootRoutine);
}
private IEnumerator CoFire()
{
while (true)
{
Instantiate(bulletPrefab, firePos.position, firePos.rotation);
yield return new WaitForSeconds(0.5f);
}
}
}
public class BossMain : MonoBehaviour
{
[SerializeField]
private CJoystick1 joystick1;
[SerializeField]
private Player player;
[SerializeField]
private FireController fireController;
private bool isDown;
// Start is called before the first frame update
void Start()
{
this.joystick1.onDown = () =>
{
this.isDown = true;
this.fireController.StopFire();
};
this.joystick1.onUp = () =>
{
this.isDown = false;
this.player.Attack();//아래에서 dir=vector3.zero 면 idle 실행하는거 썼는데 왜 여기다가 또 썼을까?
this.fireController.Fire();
};
}
최종적으로 이렇게 고치니 제대로 된다.

코드 재정비 하기
- 따로 FireController 스크립트를 만들지 말고 Player 스크립트에다가 쓰기!!! (나중에 오브젝트 풀링으로 총알 발사구현할때 다 쓰면 idle상태가 되어야하는데 그때 Player내에 있어야 좋을거같음)
using System.Collections;
using System.Collections.Generic;
using System.Xml.Serialization;
using UnityEngine;
public class Player : MonoBehaviour
{
[SerializeField]
private float moveSpeed = 1f;
[SerializeField]
private Animator anim;
private Rigidbody rBody;
[SerializeField]
private GameObject bossPrefab;
public System.Action onReachPortal;
//총알발사
[SerializeField]
private GameObject bulletPrefab;
[SerializeField]
private Transform firePos;
private IEnumerator shootRoutine;
private void Start()
{
shootRoutine = CoFire();
this.rBody = this.GetComponent<Rigidbody>();
this.Idle();
}
// Start is called before the first frame update
public void Move(Vector3 dir)
{
this.rBody.isKinematic = false;
this.anim.SetInteger("State", 1);
//마우스 드래그 각도 구하기
var angle = Mathf.Atan2(dir.x, dir.z) * Mathf.Rad2Deg;
var q = Quaternion.AngleAxis(angle, Vector3.up);
//마우스 각도만큼 회전시키고 그 방향으로(forward)이동하기
this.transform.rotation = q;
this.transform.Translate(Vector3.forward * this.moveSpeed * Time.deltaTime);
this.StopFire();
}
public void Idle()
{
//Debug.Log("idle");
this.anim.SetInteger("State", 0);
//this.rBody.isKinematic = true;
}
// 총 쏘는 자세
public void Attack()
{
this.anim.SetInteger("State", 2);
this.transform.LookAt(this.bossPrefab.transform.position);
this.Fire();
}
//------------------------------------------------------총알 발사--------------------------------------------------------
public void Fire()
{
//Debug.Log("총알발사");
this.StartCoroutine(shootRoutine);
}
public void StopFire()
{
//Debug.Log("총알 발사 중지");
this.StopCoroutine(shootRoutine);
}
private IEnumerator CoFire()
{
while (true)
{
Instantiate(bulletPrefab, firePos.position, firePos.rotation);
yield return new WaitForSeconds(0.5f);
}
}
}
수정된 Player 스크립트
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BossMain : MonoBehaviour
{
[SerializeField]
private CJoystick1 joystick1;
[SerializeField]
private Player player;
private bool isDown;
// Start is called before the first frame update
void Start()
{
this.joystick1.onDown = () =>
{
this.isDown = true;
};
this.joystick1.onUp = () =>
{
this.isDown = false;
this.player.Attack();//아래에서 dir=vector3.zero 면 idle 실행하는거 썼는데 왜 여기다가 또 썼을까?
};
}
// Update is called once per frame
void Update()
{
//수평
var h = this.joystick1.Horizontal;
//수직
var v = this.joystick1.Vertical;
var dir = new Vector3(h, 0, v);
if (dir != Vector3.zero)
{
this.player.Move(dir);
}
//else if(dir==Vector3.zero&&isDown==false)
//this.player.Attack();
}
}
다른 스크립트는 변경사항 없음
'3D 콘텐츠 제작' 카테고리의 다른 글
| zombero-boss 3일 (0) | 2023.10.09 |
|---|---|
| zombero- boss 2일 (1) | 2023.10.08 |
| zombero 3일차(9/25) (0) | 2023.09.25 |
| zombero 2일차 (0) | 2023.09.23 |
| zombero 1일차 (0) | 2023.09.22 |