[Unity] 화살표 그리기 3종류

APP 2019. 11. 7. 13:03
using UnityEngine;
using System.Collections;

public static class DrawArrow
{
    public static void ForGizmo(Vector3 pos, Vector3 direction, float arrowHeadLength = 0.25f, float arrowHeadAngle = 20.0f)
    {
        Gizmos.DrawRay(pos, direction);

        Vector3 right = Quaternion.LookRotation(direction) * Quaternion.Euler(0, 180 + arrowHeadAngle, 0) * new Vector3(0, 0, 1);
        Vector3 left = Quaternion.LookRotation(direction) * Quaternion.Euler(0, 180 - arrowHeadAngle, 0) * new Vector3(0, 0, 1);
        Gizmos.DrawRay(pos + direction, right * arrowHeadLength);
        Gizmos.DrawRay(pos + direction, left * arrowHeadLength);
    }

    public static void ForGizmo(Vector3 pos, Vector3 direction, Color color, float arrowHeadLength = 0.25f, float arrowHeadAngle = 20.0f)
    {
        Gizmos.color = color;
        Gizmos.DrawRay(pos, direction);

        Vector3 right = Quaternion.LookRotation(direction) * Quaternion.Euler(0, 180 + arrowHeadAngle, 0) * new Vector3(0, 0, 1);
        Vector3 left = Quaternion.LookRotation(direction) * Quaternion.Euler(0, 180 - arrowHeadAngle, 0) * new Vector3(0, 0, 1);
        Gizmos.DrawRay(pos + direction, right * arrowHeadLength);
        Gizmos.DrawRay(pos + direction, left * arrowHeadLength);
    }

    public static void ForDebug(Vector3 pos, Vector3 direction, float arrowHeadLength = 0.25f, float arrowHeadAngle = 20.0f)
    {
        Debug.DrawRay(pos, direction);

        Vector3 right = Quaternion.LookRotation(direction) * Quaternion.Euler(0, 180 + arrowHeadAngle, 0) * new Vector3(0, 0, 1);
        Vector3 left = Quaternion.LookRotation(direction) * Quaternion.Euler(0, 180 - arrowHeadAngle, 0) * new Vector3(0, 0, 1);
        Debug.DrawRay(pos + direction, right * arrowHeadLength);
        Debug.DrawRay(pos + direction, left * arrowHeadLength);
    }
    public static void ForDebug(Vector3 pos, Vector3 direction, Color color, float arrowHeadLength = 0.25f, float arrowHeadAngle = 20.0f)
    {
        Debug.DrawRay(pos, direction, color);

        Vector3 right = Quaternion.LookRotation(direction) * Quaternion.Euler(0, 180 + arrowHeadAngle, 0) * new Vector3(0, 0, 1);
        Vector3 left = Quaternion.LookRotation(direction) * Quaternion.Euler(0, 180 - arrowHeadAngle, 0) * new Vector3(0, 0, 1);
        Debug.DrawRay(pos + direction, right * arrowHeadLength, color);
        Debug.DrawRay(pos + direction, left * arrowHeadLength, color);
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Arrow : MonoBehaviour
{
    public Character ch1;
    public Character ch2;
    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        
    }
    void OnDrawGizmos()
    {
        Gizmos.color = Color.yellow;
        DrawArrow.ForGizmo(ch1.transform.position, InGame.sttGetVectorAToB(ch1, ch2) * InGame.sttGetDistance(ch1, ch2), Color.white);
    }
}

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

public class InGame : MonoBehaviour
{
    private Hero hero;
    private Monster monster;
    private Npc chicken;   
    // Start is called before the first frame update
    void Start()
    {

    }

    // Update is called once per frame
    void Update()
    {
       // DrawArrow.ForDebug(chicken.transform.position, GetVectorAToB(chicken, monster) * GetDistance(chicken, monster), Color.white);
    }

    internal void StartGame()
    {


        this.hero = CreateCharacter("Hero") as Hero;
        this.monster = CreateCharacter("Monster") as Monster;

        GameObject model1 = Resources.Load("Boximon Cyclopes");
        GameObject model2 = Resources.Load("Boximon Fiery");

        GameObject monsterModelGo = Instantiate(model1);
        GameObject heroModelGo = Instantiate(model2);

        monsterModelGo.transform.SetParent(monster.transform.root.transform);
        heroModelGo.transform.parent = hero.transform.root.transform;
        monster.transform.root.transform.position = new Vector3(2, 0, 0);
       

        //치킨을 Npc로 추가
        this.chicken = CreateCharacter("Chicken") as Npc;
        GameObject model3 = Resources.Load("Toon Chicken");
        GameObject chicModelGo = Instantiate(model3);
        chicModelGo.transform.parent = chicken.transform.root.transform;
        chicken.transform.root.position = new Vector3(-1, 0, 0);

        hero.transform.position = new Vector3(1, 0, 3);
        monster.transform.position = new Vector3(-1, 0, 1);
        chicken.transform.position = new Vector3(1, 0, -1);
                
        //========각각 오브젝트 사이의 벡터의 크기와 단위벡터를 구함=============
        Debug.Log($"Hero To Monster");
        Debug.Log($"Distance: {GetDistance(hero, monster)}");
        Vector3 unitVector1 = GetVectorAToB(hero, monster);
        Debug.Log(unitVector1);
        Debug.Log($"{unitVector1.x}, {unitVector1.y}, {unitVector1.z}");

        Debug.Log($"Monster To Hero");
        Debug.Log($"Distance: {GetDistance(monster, hero)}");
        Vector3 unitVector2 = GetVectorAToB(monster, hero);
        Debug.Log($"{unitVector2.x}, {unitVector2.y}, {unitVector2.z}");

        Debug.Log($"Hero To Chicken");
        Debug.Log($"Distance: {GetDistance(hero, chicken)}");
        Vector3 unitVector3 = GetVectorAToB(hero, chicken);
        Debug.Log($"{unitVector3.x}, {unitVector3.y}, {unitVector3.z}");

        Debug.Log($"Chicken To Hero");
        Debug.Log($"Distance: {GetDistance(chicken, hero)}");
        Vector3 unitVector4 = GetVectorAToB(chicken, hero);
        Debug.Log($"{unitVector4.x}, {unitVector4.y}, {unitVector4.z}");

        Debug.Log($"Chicken To Monster");
        Debug.Log($"Distance: {GetDistance(chicken, monster)}");
        Vector3 unitVector5 = GetVectorAToB(chicken, monster);
        Debug.Log($"{unitVector5.x}, {unitVector5.y}, {unitVector5.z}");

        Debug.Log($"Monster To Chicken");
        Debug.Log($"Distance: {GetDistance(monster, chicken)}");
        Vector3 unitVector6 = GetVectorAToB(monster, chicken);
        Debug.Log($"{unitVector6.x}, {unitVector6.y}, {unitVector6.z}");


        /*
        //========================================================================

        
        //디버그의 DrawLine으로도 선을 그릴 수 있다.
        //Debug.DrawLine(Vector3.zero, new Vector3(1, 0, 0), Color.red, 100f);

        //line이라는 게임오브젝트를 만들어서 컴포넌트로 LineRenderer를 붙인다.
        GameObject line = new GameObject("ChicToHero");
        LineRenderer line1 = line.AddComponent();

        //subLine이라는 게임오브젝트를 만들어서 컴포넌트로 LineRenderer를 붙이고, 그 부모를 line으로 설정한다.
        GameObject subLine = new GameObject("subLine");
        //subLine의 LineRenderer를 line2에 대입한다. 해당 LineRenderer를 제어하기 위함이다.
        LineRenderer line2 = subLine.AddComponent();
        subLine.transform.parent = line.transform;         
        line2.useWorldSpace = false;

        //치킨의 벡터와 히어로의 벡터를 벡터배열로 만든다. 이는 LineRenderer의 시작점과 끝점에 넣기 위함이다.
        Vector3[] vectorChicToHero = { chicken.transform.position, hero.transform.position};
        //라인렌더러의 시작점과 끝점에 위의 벡터를 대입한다.
        line1.SetPositions(vectorChicToHero);        
        //라인의 굵기를 결정한다.
        line1.startWidth=0.1f;
        line1.endWidth = 0.1f;
        //라인의 색상을 결정한다.
        line1.startColor = Color.white;
        line1.endColor = Color.white;
        //라인의 재질을 결정한다.
        line1.material = new Material(Shader.Find("Sprites/Default"));


        //subLine의 Linerenderer인 line2의 굵기,색상,재질을 결정한다.
        line2.startWidth = 0.1f;
        line2.endWidth = 0.1f;
        line2.startColor = Color.white;
        line2.endColor = Color.white;
        line2.material = new Material(Shader.Find("Sprites/Default"));

        //line2는 line1과는 달리 3개의 점을 지나친다. 그러므로 positionCount를 3으로 설정한다.
        line2.positionCount = 3;
       
        //처음에 세 점을 결정할 때, 단순히 히어로의 포지션을 기준으로 x, z 좌표에 변화를 준 값으로 설정했다.
        //Vector3 vector0 = new Vector3 ( hero.transform.position.x - 0.5f, hero.transform.position.y, hero.transform.position.z - 0.5f);
        //Vector3 vector1 = hero.transform.position;
        //Vector3 vector2 = new Vector3(hero.transform.position.x + 0.5f, hero.transform.position.y, hero.transform.position.z - 0.5f);

        //이후에 세 점을 결정할 때, 부모인 line1의 끝점을 기준으로 x,z좌표에 변화를 준 값으로 설정했다.
        Vector3 vector0 = new Vector3( line1.GetPosition(1).x- 0.5f, line1.GetPosition(1).y, line1.GetPosition(1).z- 0.5f);
        Vector3 vector1 = new Vector3(line1.GetPosition(1).x, line1.GetPosition(1).y, line1.GetPosition(1).z);
        Vector3 vector2 = new Vector3(line1.GetPosition(1).x + 0.5f, line1.GetPosition(1).y, line1.GetPosition(1).z- 0.5f);
        Vector3[] vectorLine2 = { vector2, vector1, vector0 };
        line2.SetPositions(vectorLine2);
        */

        //DrawArrow.ForGizmo(unitVector5 * GetDistance(chicken, monster), unitVector5);
        // DrawArrow.ForDebug(chicken.transform.position, unitVector5);
        chicken.target = monster;

        GameObject arrowGo = new GameObject("Arrow");
        Arrow arrow = arrowGo.AddComponent();
        arrow.ch1 = chicken;
        arrow.ch2 = monster;


        
    }
   
    //캐릭터에 T에 들어온 타입의 컴포넌트를 붙여서 캐릭터를 반환한다. 게임오브젝트의 이름은 매개변수로 받는다.
    public Character CreateCharacter(string name) where T : Character
    {
        GameObject go = new GameObject(name);
        T character = go.AddComponent();
        return character;
    }
    //두개의 Monobehaviour를 매개변수로 받고, 둘 사이의 거리를 구해서 float으로 반환한다.
    public float GetDistance(MonoBehaviour a, MonoBehaviour b)
    {
        float x1;
        float y1;
        float z1;
        float x2;
        float y2;
        float z2;
        x1 = a.transform.position.x;
        y1 = a.transform.position.y;
        z1 = a.transform.position.z;
        x2 = b.transform.position.x;
        y2 = b.transform.position.y;
        z2 = b.transform.position.z;

        float distance = (float)Math.Sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2) + (z1 - z2) * (z1 - z2));
        //Debug.Log(distance);
        return distance;
    }
    //벡터 A에서 B로 향하는 벡터의 단위벡터를 구한다.
    public Vector3 GetVectorAToB(MonoBehaviour a, MonoBehaviour b)
    {
        float x = b.transform.position.x - a.transform.position.x;
        float y = b.transform.position.y - a.transform.position.y;
        float z = b.transform.position.z - a.transform.position.z;
        float dist = GetDistance(a, b);
        Vector3 unitVector = new Vector3(x/dist, y/dist, z/dist);
        return unitVector;
    }
    public static float sttGetDistance(MonoBehaviour a, MonoBehaviour b)
    {
        float x1;
        float y1;
        float z1;
        float x2;
        float y2;
        float z2;
        x1 = a.transform.position.x;
        y1 = a.transform.position.y;
        z1 = a.transform.position.z;
        x2 = b.transform.position.x;
        y2 = b.transform.position.y;
        z2 = b.transform.position.z;

        float distance = (float)Math.Sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2) + (z1 - z2) * (z1 - z2));
        //Debug.Log(distance);
        return distance;
    }
    //벡터 A에서 B로 향하는 벡터의 단위벡터를 구한다.
    public static Vector3 sttGetVectorAToB(MonoBehaviour a, MonoBehaviour b)
    {
        float x = b.transform.position.x - a.transform.position.x;
        float y = b.transform.position.y - a.transform.position.y;
        float z = b.transform.position.z - a.transform.position.z;
        float dist = sttGetDistance(a, b);
        Vector3 unitVector = new Vector3(x / dist, y / dist, z / dist);
        return unitVector;
    }
}

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

public class Character : MonoBehaviour
{
    public Character target;
    public Character focus;
    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        
    }
    void OnDrawGizmos()
    {
        Gizmos.color = Color.yellow;
        DrawArrow.ForGizmo(this.transform.root.position, InGame.sttGetVectorAToB(this, target) * InGame.sttGetDistance(this, target), Color.white);
    }
}

: