[마블 VR] 첫번째 포인트 도착 구현
오늘 해야할 일
1. 첫번째 포인트로 이동하면 찍기 튜토리얼 나오기 - 오전
2. 찍기 튜토리얼 할 때는 공격하지 않고, 가까운 적 한마리 생성하기 - 오전
3. 두번째 적 모두 죽이면 다시 인디케이터+ 자동이동 - 오전
4. 두번째 포인트 도착하면 리프 튜토리얼 나오기 - 오후
5. 두번째 적 움직임 구현 - 오후
6. 못끝낸거 있다면 - 저녁
내일은 근접공격이랑 원거리 공격 합치기
1. 첫번째 포인트에 도착하면 찍기 튜토리얼 나오기
찍기 튜토리얼이 아직 만들어지지 않아서 일단 로그로 찍고, indexTrigger버튼 누르면 적이 나오도록 만들었다.
<Playercontroller.cs>
private void OnTriggerEnter(Collider other)
{
if (other.CompareTag("Point"))
{
Debug.Log("목적지에 도착했습니다");
//인디케이터 지우고 이동 멈추기
this.indicatorGo.SetActive(false);
this.pathGo.SetActive(false);
if (this.coroutine != null) StopCoroutine(this.coroutine);
//근거리 공격 튜토리얼
Debug.Log("근거리 공격 튜토리얼");
if (OVRInput.GetDown(OVRInput.Button.SecondaryIndexTrigger))
{
Debug.Log("찍기 완료");
//근거리 공격 튜토리얼 끝나면 isFirstEnemy false로 만들기
this.gameSceneMain.isFirstEnemy = false;
this.gameSceneMain.enemyNum = 0;
}
}
}
===> 이렇게 하면 triggerEnter가 딱 들어왔을때 한번만 호출되므로 트리거버튼 눌러도 생성되지 않는다
임의로 전에 만들어뒀던 leapUI를 일단 쓰자
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class LeapMain : MonoBehaviour
{
public GameObject step1High;
public GameObject step2High;
public GameObject setp1;
public GameObject setp2;
private Animator anim;
private GameSceneMain gameSceneMain;
private void Start()
{
this.gameSceneMain = GameObject.FindObjectOfType<GameSceneMain>();
Invoke("Active", 2f);
StartCoroutine(CoGrab());
this.anim = GetComponent<Animator>();
}
private void Active()
{
this.step1High.SetActive(true);
this.setp1.SetActive(false);
}
IEnumerator CoGrab()
{
while (true)
{
if (OVRInput.GetDown(OVRInput.Button.One, OVRInput.Controller.RTouch))
{
Debug.Log("step1완료");
this.step1High.gameObject.SetActive(false);
this.setp1.SetActive(true);
this.step2High.gameObject.SetActive(true);
this.setp2.SetActive(false);
}
else if (OVRInput.GetUp(OVRInput.Button.One, OVRInput.Controller.RTouch))
{
Debug.Log("step2완료");
this.step2High.gameObject.SetActive(false);
this.setp2.SetActive(true);
//적 생성하기
this.gameSceneMain.isFirstEnemy = false;
this.gameSceneMain.enemyNum = 0;
Destroy(this.gameObject, 0.2f);
}
yield return null;
}
}
}
using Meta.WitAi;
using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.UI;
public class PlayerController : MonoBehaviour
{
[SerializeField]
private PathMain pathMain;
[SerializeField]
private GameObject indicatorGo;
[SerializeField]
private Transform destination;
[SerializeField]
private Transform[] pos;
[SerializeField] Transform leapPos;
[SerializeField] ParticleSystem warp;
[SerializeField] private GameObject closeTutorial;
public GameObject pathGo;
public float ms = 0.025f;
private Coroutine coroutine;
//float curTime = 0;
//float warpTime = 0.5f;
// Start is called before the first frame update
void Start()
{
this.coroutine = this.StartCoroutine(this.CoMove());
}
private IEnumerator CoMove()
{
yield return new WaitForSeconds(1f);
while (true)
{
var dis = Vector3.Distance(this.transform.position, destination.position);
if (dis < 9f)
{
this.transform.position = Vector3.MoveTowards(this.transform.position, pos[2].position, ms);
}
else
{
this.transform.position = Vector3.MoveTowards(this.transform.position, pos[1].position, ms);
}
yield return null;
}
}
private void OnTriggerEnter(Collider other)
{
if (other.CompareTag("Point"))
{
Debug.Log("목적지에 도착했습니다");
//인디케이터 지우고 이동 멈추기
this.indicatorGo.SetActive(false);
this.pathGo.SetActive(false);
if (this.coroutine != null) StopCoroutine(this.coroutine);
//근거리 공격 튜토리얼
Debug.Log("근거리 공격 튜토리얼 생성");
Instantiate(this.closeTutorial);
}
}
}
나중에 근접공격UI(찍기 튜토리얼)으로 변경될 예정
튜토리얼이 완료되면 적이 생성되도록 만들었다.
결과물
2. 찍기 튜토리얼 할 때는 공격하지 않고, 가까운 적 한마리 생성하기
찍기 튜토리얼 (지금은 leap튜토리얼) 하는 동안에 근접공격 튜토리얼용 공격하지 않는 가까운 적 한마리를 생성하자
그리고 leap 튜토리얼이 끝나면 그 적은 사라지게 한다. ( 나중에는 근접공격 튜토리얼에서 근접공격을 통해 적이 죽으면)
실제 전투용 적을 생성한다
코드로 말고 간단하게 애니메이션으로 움직임 구현한다.
<PlayerController>
private void OnTriggerEnter(Collider other)
{
if (other.CompareTag("Point"))
{
Debug.Log("목적지에 도착했습니다");
//인디케이터 지우고 이동 멈추기
this.indicatorGo.SetActive(false);
this.pathGo.SetActive(false);
if (this.coroutine != null) StopCoroutine(this.coroutine);
//근거리 공격 튜토리얼
Instantiate(this.closeTutorial);
//튜토리얼용 적 생성
this.tutorialAerialEnemy.SetActive(true);
}
}
포인트에 도착하면 튜토리얼과 함께 나오도록 한다.
==> 문제점이 있음 애니메이션을 position으로 잡아서 쉴드에 맞아도 바닥으로 안떨어진다.
부딪히면 애니메이션 끄도록 함
결과
==>여기까지 했을 때 이상한 부분들..
방패 팔에 붙는거 위치나 모양새가 이상
방패 날라가는거 방향,, 상당히 수정 필요해보임
살짝 이상한 부분은 아무래도 아래에 적은 튜토리얼 넘어가는 부분
3. 두번째 적 모두 죽이면 다시 인디케이터+ 자동이동
path가 생긴게 다르기 때문에 두개를 만들었다.
public GameObject[] pathGo;
배열로 만들고
public void CreateEnemy()
{
if (this.enemyGo.Length == 0)
{
//첫번째 포인트에서 생성되는 적임(최대 8마리 3-3-2)
if (isFirstEnemy == true)
{
if (enemyNum < 6)
{
//적 3마리 생성
for (int i = 0; i < 3; i++)
{
//Debug.Log("적 생성해라");
Instantiate(this.aerialEnemyPrefab, this.points[i].position, Quaternion.identity);
enemyNum++;
}
}
else if (enemyNum >= 6 && enemyNum < 8)
{
//2마리 생성
for (int i = 0; i < 2; i++)
{
Instantiate(this.aerialEnemyPrefab, this.points[i].position, Quaternion.identity);
enemyNum++;
}
}
else
{
//더이상 생성하지 X
//첫번째 인디케이터 생성
this.playerController.pathGo[0].SetActive(true);
this.playerController.GetComponent<PlayerController>().enabled = true;
return;
}
}
//두번째 포인트에서 생성되는 적임(최대 7마리 2-2-1)
else
{
if (enemyNum < 4)
{
for (int i=3;i<5; i++)
{
Instantiate(this.aerialEnemyPrefab, this.points[i].position, Quaternion.identity);
enemyNum++;
}
}
else if (enemyNum >= 4&&enemyNum<5 )
{
Instantiate(this.aerialEnemyPrefab, this.points[5].position, Quaternion.identity);
enemyNum++;
}
else
{
//두번째 인디케이터 생성
this.playerController.pathGo[1].SetActive(true);
return;
}
}
}
}
첫번째 적이 모두 죽으면 첫번째 인디케이터 활성화,
두번째 적이 모두 죽으면 두번째 인디케이터를 활성화 해줌
자동이동 구현하기
indicator(원모양 포인트)도 두개가 필요하니까 배열로 만들어주고,
using Meta.WitAi;
using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.UI;
public class PlayerController : MonoBehaviour
{
[SerializeField]
private PathMain pathMain;
[SerializeField]
private GameObject[] indicatorGo;
[SerializeField]
private Transform[] pos;
[SerializeField] Transform leapPos;
[SerializeField] ParticleSystem warp;
[SerializeField] private GameObject closeTutorial;
[SerializeField] private GameObject tutorialAerialEnemy;
public GameObject[] pathGo;
public float ms = 0.025f;
private Coroutine coroutine;
private bool isSecond;
//float curTime = 0;
//float warpTime = 0.5f;
void Start()
{
this.Move();
}
public void Move()
{
this.coroutine = this.StartCoroutine(this.CoMove());
}
public void SecondMove()
{
this.coroutine = this.StartCoroutine(this.CoSecondMove());
}
private IEnumerator CoMove()
{
yield return new WaitForSeconds(1.3f);
while (true)
{
var dis = Vector3.Distance(this.transform.position, indicatorGo[0].transform.position);
if (dis < 9f)
{
this.transform.position = Vector3.MoveTowards(this.transform.position, pos[1].position, ms);
}
else
{
this.transform.position = Vector3.MoveTowards(this.transform.position, pos[0].position, ms);
}
yield return null;
}
}
private IEnumerator CoSecondMove()
{
yield return new WaitForSeconds(1.3f);
while (true)
{
var dis = Vector3.Distance(this.transform.position, indicatorGo[1].transform.position);
if (dis < 9f)
{
this.transform.position = Vector3.MoveTowards(this.transform.position, pos[3].position, ms);
}
else
{
this.transform.position = Vector3.MoveTowards(this.transform.position, pos[2].position, ms);
}
yield return null;
}
}
private void OnTriggerEnter(Collider other)
{
if (other.CompareTag("Point"))
{
Debug.Log("목적지에 도착했습니다");
//인디케이터 지우고 이동 멈추기
this.indicatorGo[0].SetActive(false);
this.pathGo[0].SetActive(false);
if (this.coroutine != null) StopCoroutine(this.coroutine);
//근거리 공격 튜토리얼
Instantiate(this.closeTutorial);
//튜토리얼용 적 생성
this.tutorialAerialEnemy.SetActive(true);
}
//두번째 포인트일때
}
}
gameMain에서
여러번 호출되는거를 막기 위해서 바로 false로 만들어줬다.
문제점. 1. 쳐다보는 방향
-> LookAt을 추가함 하지만 너무 갑자기 휙 돌아버려서 이상함 lerp로 부드럽게 보도록 하기
if (dis < 9f)
{
var dir = pos[3].position - this.transform.position;
this.transform.rotation = Quaternion.Lerp(this.transform.rotation, Quaternion.LookRotation(dir), Time.deltaTime * 0.2f);
this.transform.position = Vector3.MoveTowards(this.transform.position, pos[3].position, ms);
}
2. 이동 위치 이상
현재 포인트가 2개이기때문에 자연스럽지 않음=> 3개로 늘려야할거같다.
각 포인트에서 도착 지점까지의 거리를 구하고
private IEnumerator CoSecondMove()
{
yield return new WaitForSeconds(1.3f);
while (true)
{
var dis = Vector3.Distance(this.transform.position, indicatorGo[1].transform.position);
if (dis < 7f)
{
var dir = pos[4].position - this.transform.position;
this.transform.rotation = Quaternion.Lerp(this.transform.rotation, Quaternion.LookRotation(dir), Time.deltaTime * 0.15f);
this.transform.position = Vector3.MoveTowards(this.transform.position, pos[4].position, ms);
}
else if(dis<11f&&dis>7f)
{
var dir = pos[3].position - this.transform.position;
this.transform.rotation = Quaternion.Lerp(this.transform.rotation, Quaternion.LookRotation(dir), Time.deltaTime * 0.15f);
this.transform.position = Vector3.MoveTowards(this.transform.position, pos[3].position, ms);
}
else
{
this.transform.position = Vector3.MoveTowards(this.transform.position, pos[2].position, ms);
}
yield return null;
}
}
결과
위치는 자연스러워졌다. 하지만 회전이 더 빨리 되어야할거같음
4. 두번째 포인트 도착하면 리프 튜토리얼 나오기
private void OnTriggerEnter(Collider other)
{
if (other.CompareTag("Point"))
{
Debug.Log("목적지에 도착했습니다");
//인디케이터 지우고 이동 멈추기
this.indicatorGo[0].SetActive(false);
this.pathGo[0].SetActive(false);
if (this.coroutine != null) StopCoroutine(this.coroutine);
//근거리 공격 튜토리얼
Instantiate(this.leapTutorial);
//튜토리얼용 적 생성
this.tutorialAerialEnemy.SetActive(true);
}
else if (other.CompareTag("SecondPoint"))
{
this.indicatorGo[1].SetActive(false);
this.pathGo[1].SetActive(false);
if (this.coroutine != null) StopCoroutine(this.coroutine);
//리프 튜토리얼 나오기
Instantiate(this.leapTutorial,new Vector3(-25.8f,1.3f,5.2f),Quaternion.Euler(0,68f,0));
}
}
else if (OVRInput.GetUp(OVRInput.Button.PrimaryHandTrigger, OVRInput.Controller.LTouch))
이렇게 하면, 방패가 날라가지 않았는데도 다음 튜토리얼로 넘어감
그래서
else if (!OVRInput.Get(OVRInput.Button.PrimaryHandTrigger, OVRInput.Controller.LTouch) && av >= 0.42)
GetUp+ 속도 까지 하면 너무 확률이 희박해져서
!Get&&속도 이렇게 함
또 문제점, 이렇게 하면 버튼 안누른 상태로 컨트롤러 빠르게 움직이면 다음 튜토리얼로 넘어감..
if (OVRInput.GetDown(OVRInput.Button.PrimaryHandTrigger, OVRInput.Controller.LTouch))
{
Debug.Log("step1완료");
this.step1High.gameObject.SetActive(false);
this.setp1.SetActive(true);
this.step2High.gameObject.SetActive(true);
this.setp2.SetActive(false);
this.isButtonUp = true;
}
else if (!OVRInput.Get(OVRInput.Button.PrimaryHandTrigger, OVRInput.Controller.LTouch) && av >= 0.42&&isButtonUp==true)
그래서 bool을 넣어줌
하지만 또 이러면 trigger버튼 한번 누르고 다시 떼고 컨트롤러 빠르게 움직이면 또 다음 튜토리얼로 넘어가버림