게임 엔진/Unity

[Unity] [Example] 평면 연산 방법 (Plane)

AlgorFati 2020. 7. 28. 11:07

Plane

유니티 Plane 예제이다.

GameObject의 위치를 기준으로 4방에 평면 4개를 배치하고,

8방향으로 각 평면에 Raycast를 하여 거리를 재는 예제이다.

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class SnakeAgent : MonoBehaviour
{
	private static readonly Vector3Int Forward = new Vector3Int(0, 0, 1);
	private static readonly Vector3Int Back = new Vector3Int(0, 0, -1);
	private static readonly Vector3Int Left = new Vector3Int(-1, 0, 0);
	private static readonly Vector3Int Right = new Vector3Int(1, 0, 0);

	private const int MinX = -8;
	private const int MaxX = 8;
	private const int MinZ = -8;
	private const int MaxZ = 8;

	private Vector3Int _direction = Forward;

	private Plane _leftBoundPlane;

	private Plane _rightBoundPlane;

	private Plane _forwardBoundPlane;

	private Plane _backBoundPlane;
	
	private Vector3[] _directions;

	[SerializeField]
	private int[] _wallDistances = new int[8];

	private void Awake()
	{
		_directions = new Vector3[8]
		{
			(Vector3.forward + Vector3.left).normalized,
			Vector3.forward,
			(Vector3.forward + Vector3.right).normalized,
			Vector3.right,
			(Vector3.back + Vector3.right).normalized,
			Vector3.back,
			(Vector3.back + Vector3.left).normalized,
			Vector3.left,
		};

		Vector3 parentPos = transform.parent.localPosition;


		_leftBoundPlane = new Plane(Right, parentPos + new Vector3(MinX, 0, 0));

		_rightBoundPlane = new Plane(Left, parentPos + new Vector3(MaxX, 0, 0));

		_forwardBoundPlane = new Plane(Back, parentPos + new Vector3(0, 0, MaxZ));

		_backBoundPlane = new Plane(Forward, parentPos + new Vector3(0, 0, MinZ));
	}

	private void Update()
	{
		MakeDistancesToWall();
	}

	private void MakeDistancesToWall()
	{
		Transform headTransform = transform.GetChild(0);
		Vector3 headPos = headTransform.position;
		Vector3 planePos;
		float distance;

		for (int i = 0; i < _wallDistances.Length; ++i)
		{
			_wallDistances[i] = -1;
		}
		
		for (int i = 0; i < _directions.Length; ++i)
		{
			Vector3 dir = _directions[i];

			if (i == 0 || i == 1 || i == 2)
			{
				if (PosOnPlane(new Ray(headPos, dir), _forwardBoundPlane, out planePos, out distance))
				{
					_wallDistances[i] = Mathf.RoundToInt(distance);
				}
			}
			else if (i == 3)
			{
				if (PosOnPlane(new Ray(headPos, dir), _rightBoundPlane, out planePos, out distance))
				{
					_wallDistances[i] = Mathf.RoundToInt(distance);
				}
			}
			else if (i == 4 || i == 5 || i == 6)
			{
				if (PosOnPlane(new Ray(headPos, dir), _backBoundPlane, out planePos, out distance))
				{
					_wallDistances[i] = Mathf.RoundToInt(distance);
				}
			}
			else if (i == 7)
			{
				if (PosOnPlane(new Ray(headPos, dir), _leftBoundPlane, out planePos, out distance))
				{
					_wallDistances[i] = Mathf.RoundToInt(distance);
				}
			}
		}
	}


	private static bool PosOnPlane(Ray ray, Plane plane, out Vector3 pos, out float distance)
	{
		if (plane.Raycast(ray, out distance))
		{
			pos = ray.GetPoint(distance);
			return true;
		}
		else
		{
			pos = Vector3.zero;
			distance = -1;
			return false;
		}
	}
}