오늘도 어김없이.. 파일부터 만들고
큐브를 만들고 Parent 이름 바꿔주고
위치값을 초기화 합니다.
그리고 자식으로 큐브 하나 더 만든다음 Child로 이름을 지정합니다.
그리고 위와같이 크기, 위치 조장해주면
이정도로 거리를 둔 상태가 됩니다.
부모의 위치를 바꾸면 자식은 그냥 따라오고 회전도 동일하다.
자식을 조절하면 자식만 바뀐다
부모의 위치값이 바뀌면 자식은
그대로 이다 자식은 자식이 되었을대 상대좌표가 되기 때문에 부모를 기준으로한다.
그리고 컨트롤D를 눌러 자식을 늘리고 위치를 이렇게 바꾸면
그리고 스크립트 폴더에 HierarchyExample 라고 지정하고 부모에 스크립트를 넣습니다
그 전에
자식 오브젝트들을 이렇게 바꿔줍니다.
public class HierarchyExample : MonoBehaviour
{
private void Start()
{
Transform tr = GetComponent<Transform>(); //
Transform childTr = GetComponentInChildren<Transform>(gameObject);//자식의 트랜스폼을 가져온다
Debug.Log("childTr : " + childTr.name); // 출력
}
}
그리고 Child 를 하나 더 만들어준 다음에
Child3에 넣어준다음
그리고 HierarchyExample 에 밑에 코드를 넣어주면
Child child = GetComponentInChildren<Child>();
Debug.Log("child :" + child.name);
출력 결과
예상과는 많이 다르다.
Transform[] childTrs = GetComponentsInChildren<Transform>(childTr);
Debug.Log("childTrs Length: " + childTrs.Length);
for(int i = 0; i < childTrs.Length; ++i)
{
Debug.LogFormat("childTrs[{0}] : {1}", i, childTrs[i].name);
}
그리고 위와같이 추가하고 결과를 보면
부모와 함께 Length에 포함되고 모든 자식오브젝트들이 출력된다.
public class HierarchyExample : MonoBehaviour
{
private Transform testChild = null;
private void Start()
{
Transform tr = GetComponent<Transform>(); //
Transform childTr =GetComponentInChildren<Transform>(gameObject);//자식의 트랜스폼을 가져온다
Debug.Log("childTr : " + childTr.name); // 출력
Child child = GetComponentInChildren<Child>();
Debug.Log("child :" + child.name);
Transform[] childTrs = GetComponentsInChildren<Transform>(childTr);
Debug.Log("childTrs Length: " + childTrs.Length);
for(int i = 0; i < childTrs.Length; ++i)
{
Debug.LogFormat("childTrs[{0}] : {1}", i, childTrs[i].name);
}
testChild = GetComponentInChildren<Child>().transform;
}
private void Update()
{
TranslateChild();
}
private void TranslateChild()
{
testChild.position = transform.position + Vector3.up * Mathf.Abs(Mathf.Sin(Time.time * 5f));
}
}
그리고 위와같이 코드를 바꿔주면 ?
원래는 위아래로 곡선을 그리며 이동을 하지만 음수를 양수로 바꿔주며 움직이기 때문에 더 내려가지않는다 .
그래서 출력결과를 보면 둥실둥실 한다.
private void OnDrawGizmos()
{
Gizmos.color = Color.red;
Gizmos.DrawLine(Vector3.zero, Vector3.right);
Gizmos.color = Color.green;
Gizmos.DrawLine(Vector3.zero, Vector2.up);
Gizmos.color = Color.blue;
Gizmos.DrawLine(Vector3.zero, Vector3.forward);
Gizmos.color = Color.white;
}
함수를 추가해줍니다.
그리고 Transchild를
testChild.localPosition= Vector3.up * Mathf.Abs(Mathf.Sin(Time.time * 5f));
원래는 부모와는 상관없이 월드를 기준으로 움직다면 이렇게 바꿔주면 부모를 기준으로 상대적인 위치로 움직인다 인다.
private void RotateChild()
{
//testChild.rotation 사원 수
testChild.localRotation = Quaternion.Euler(0f, Time.time * 100f, 0f);
}
함수를 만들어줍니다.
그리고 Update 에 ScaleChild(); 를 넣어주고
역시나 함수를 바로 만들어줍니다 .
private void ScaleChild()
{
testChild.localScale = Vector3.one * Mathf.Sin(Time.time * 5f);
}
이러면 실행결과는 크기가 조금씩 바뀐다.
이래됨.
Gimbal Lock 개념
https://youtu.be/zc8b2Jo7mno?si=GsVsz-1q_aHTEXIG
그리고 부모 의 뷰를 끄고
50 0 50 의 땅을 만들어줍니다. 그리고 Y축으로 -0.5만큼 내려줍니다 .
그리고 카메라의 위치값을 위와같이 설정하고
바닥에 머테리얼 넣어줍니다.
그리고 큐브 한개 더 만들어서
큐브로 플레이어 큐브 하나 만들고 자식노드로 큐브 하나 더 만들어서 정면방향을 나타내 줍니다.
이런식으로 만든 다음 M_HeadCube 머테리얼을 만들어주고 빨간색을 줍니다
그리고 PlayerCube 스크립트를 만들고 플레이어에게 붙여줍니다 .
public class PlayerCube : MonoBehaviour
{
[SerializeField, Range(1f, 10f)]private float moveSpeed = 10f;
private void Update()
{
}
private void Move()
{
if (Input.GetKey(KeyCode.W))
{
transform.position = transform.position + (Vector3.forward * moveSpeed * Time.deltaTime);
}
if (Input.GetKey(KeyCode.S))
{
transform.Translate(Vector3.back * moveSpeed * Time.deltaTime);
}
}
}
스크립트를 넣습니다
그리고 Update에 RotateCube();넣어주고 함수를 만들어줍니다.
private void RotateCube()
{
if (Input.GetKey(KeyCode.Q)) {
transform.Rotate(Vector3.up, rotSpeed * Time.deltaTime);
}
if (Input.GetKey(KeyCode.E))
{
Vector3 newRot = transform.rotation.eulerAngles;
newRot.y += rotSpeed * Time.deltaTime;
transform.rotation = Quaternion.Euler(newRot);
}
}
이러면 W가 이상하게 동작하는데 그 이유는
if (Input.GetKey(KeyCode.W))
{
transform.position = transform.position + (Vector3.forward * moveSpeed * Time.deltaTime);
}
이 정면좌표는 월드를 기준으로 하기때문에 원하는대로 회전하면 서 갈수가 없다. 그렇다면 수정을 해주면 된다.
transform.position = transform.position + (transform.forward * moveSpeed * Time.deltaTime);
이렇게 하면 원하는대로 조작할수가 있다.
그리고 빈 오브젝트로 WallHodler
를 만들고 위와같이 cube로 Wall_L로 만들어줍니다.
그리고 상 하 좌 우 를 적절하게 조절 해주면
이렇게 됩니다. 색깔은 알아서 넣어주면 된다.
그리고 메인 카메라를 플레이어의 자식으로 하면
카메라도 움직이고
그리고 플레이어에 Rigidbody를 놓고 Freeze Rotation xyz 를 고정시켜 준다.
그리고 MoveCubeWithRB() 를 아까처럼 넣어주고 함수를 만듭니다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UIElements;
using UnityEngine.XR;
public class PlayerCube : MonoBehaviour
{
[SerializeField, Range(10f, 30f)] private float moveSpeed = 30f;
[SerializeField, Range(50f, 100f)] private float rotSpeed = 100f;
Rigidbody rb = null;
private void Update()
{
RotateCube();
//MoveCube();
MoveCubeWithRB();
}
private void Awake()
{
rb = GetComponent<Rigidbody>();
}
private void MoveCube()
{
if (Input.GetKey(KeyCode.W))
{
transform.position = transform.position + (transform.forward * moveSpeed * Time.deltaTime);
}
if (Input.GetKey(KeyCode.S))
{
transform.Translate(Vector3.back * moveSpeed * Time.deltaTime);
}
}
private void MoveCubeWithRB()
{
if (Input.GetKey(KeyCode.W))
{
rb.AddForce(transform.forward * moveSpeed);
}
if (Input.GetKey(KeyCode.S))
{
rb.AddForce(-transform.forward * moveSpeed);
}
}
private void RotateCube()
{
if (Input.GetKey(KeyCode.Q))
{
transform.Rotate(Vector3.up, rotSpeed * Time.deltaTime * -1f);
}
if (Input.GetKey(KeyCode.E))
{
Vector3 newRot = transform.rotation.eulerAngles;
newRot.y += rotSpeed * Time.deltaTime;
transform.rotation = Quaternion.Euler(newRot);
}
}
}
2024-02-14 추가 ====
private void MoveCubeWithRB()
{
if (Input.GetKey(KeyCode.W))
{
//rb.AddForce(transform.forward * moveSpeed);
//Speed : 속력
//Velocity : 속도 (방향과 힘) 유니티가 가진것중에 가장 안전한 방법이다.
rb.velocity = transform.forward * moveSpeed;
}
if (Input.GetKey(KeyCode.S))
{
//rb.AddForce(-transform.forward * moveSpeed);
rb.velocity = transform.forward * moveSpeed;
}
}