軌道予測線をUIに描画
Canvasへの描画
OnPopulateMeshをオーバーライドし、そこでメッシュを作成します。 Positionsへ軌道予測線の座標を代入し、この座標から頂点を決定し、vh.AddUIVertexQuadによって四角いポリゴンを生成します。sizeによって、座標位置を画面サイズ/2ずらし、正しい位置に頂点座標を移動しています。このScriptでは単純に頂点位置を予測線の座標をy軸へずらしただけなので、メッシュの角度によって太さが変わってしまいます。
Script
このScriptはCanvasへアタッチします。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public class UILine : Graphic { public List<Vector2> Positions = new List<Vector2>(); protected override void OnPopulateMesh(VertexHelper vh) { vh.Clear(); Vector3 size = new Vector3(Screen.width / 2, Screen.height / 2, 0); for (int i = 0; i < Positions.Count - 1; i++) { UIVertex lu, ld, ru, rd; lu = UIVertex.simpleVert; ld = UIVertex.simpleVert; ru = UIVertex.simpleVert; rd = UIVertex.simpleVert; lu.color = Color.black; ld.color = Color.black; ru.color = Color.black; rd.color = Color.black; lu.position = new Vector3(Positions[i].x, Positions[i].y + 2, 0) - size; ld.position = new Vector3(Positions[i].x, Positions[i].y - 2, 0) - size; ru.position = new Vector3(Positions[i + 1].x, Positions[i + 1].y + 2, 0) - size; rd.position = new Vector3(Positions[i + 1].x, Positions[i + 1].y - 2, 0) - size; vh.AddUIVertexQuad(new UIVertex[] { lu, ld, rd, ru }); } } } |
軌道予測線
軌道予測線の座標をListに代入し、この座標をワールド座標からスクリーン座標へ変換し、UILineのPositionsへ渡しています。OnPopulateMeshはCanvasが変更されるかGraphicのSet●●Dirtyメソッドが呼ばれない限り呼ばれないようです。そこで、uILine.SetVerticesDirty()でCanvasが更新されるようにしています。
Script
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 |
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public class UIPredictionLine : MonoBehaviour { public GameObject preBullet; public GameObject preLineRenderer; public GameObject preMarkerImage; private GameObject objBullet, objMainCamera, objMarkerImage; private Rigidbody rigBullet; private GameObject objLineRenderer; private LineRenderer lineRenderer; private Camera mainCamera; private UILine uILine; private int lineDiv = 20, rayDiv = 20; private float drag, shootPow = 0, cameraDis = -1f; private float gravity = 9.80665f, lineStep, rayStep, rotSpeed = 5f; private Vector3 hitPoint = Vector3.zero; private Vector2 vel; private List<Vector3> linePosition = new List<Vector3>(); private bool flgCursorLock = false; // Use this for initialization void Start() { objMainCamera = GameObject.Find("Main Camera"); objMainCamera.transform.position = transform.position; objMainCamera.transform.localRotation = transform.rotation; mainCamera = objMainCamera.GetComponent<Camera>(); objLineRenderer = Instantiate(preLineRenderer); objLineRenderer.transform.position = Vector3.zero; objLineRenderer.transform.eulerAngles = Vector3.zero; lineRenderer = objLineRenderer.GetComponent<LineRenderer>(); objLineRenderer.SetActive(false); Transform trfCanvas = GameObject.Find("Canvas").transform; uILine = trfCanvas.gameObject.GetComponent<UILine>(); objMarkerImage = Instantiate(preMarkerImage, trfCanvas); lineStep = 1f / lineDiv; rayStep = 1f / rayDiv; vel = new Vector2(200f * Mathf.Cos(10f * Mathf.Deg2Rad), 200f * Mathf.Sin(10f * Mathf.Deg2Rad)); } //ある時刻における座標 Vector3 GetLinePosition(float t) { float x, y; if (drag != 0) { vel = new Vector2(shootPow * Mathf.Cos(-transform.eulerAngles.x * Mathf.Deg2Rad), shootPow * Mathf.Sin(-transform.eulerAngles.x * Mathf.Deg2Rad)); float r = 1f - drag * Time.fixedDeltaTime; float n = t / Time.fixedDeltaTime; x = vel.x * Time.fixedDeltaTime * r * (1f - Mathf.Pow(r, n)) / (1f - r); y = vel.y * Time.fixedDeltaTime * r * (1f - Mathf.Pow(r, n)) / (1f - r); y = y - r * gravity * Time.fixedDeltaTime * Time.fixedDeltaTime / (1f - r) * (n - r * (1f - Mathf.Pow(r, n)) / (1f - r)); } else { x = vel.x * t; y = vel.y * t - 0.5f * gravity * (t * t + t * Time.fixedDeltaTime); } return new Vector3(0, y, x); } // Update is called once per frame void Update() { //プレイヤーの回転 transform.eulerAngles = new Vector3(gameObject.transform.eulerAngles.x - Input.GetAxis("Mouse Y") * rotSpeed, gameObject.transform.eulerAngles.y + Input.GetAxis("Mouse X") * rotSpeed, 0); linePosition.Clear(); Vector3 CameraPos = objMainCamera.transform.position; Vector3 ownPos = transform.position; if (Input.GetMouseButtonDown(0)) { //objLineRenderer.SetActive(true); objBullet = Instantiate(preBullet, ownPos, Quaternion.identity); rigBullet = objBullet.GetComponent<Rigidbody>(); drag = rigBullet.drag; } if (Input.GetMouseButton(0)) { shootPow = Mathf.Min(shootPow + 100f * Time.deltaTime, 200f); float hitPos = 1000f; //当たり判定 for (int count = 0; count < rayDiv; count++) { Vector3 startPos = Quaternion.AngleAxis(transform.eulerAngles.y, Vector3.up) * GetLinePosition(count * rayStep) + ownPos; Vector3 endPos = Quaternion.AngleAxis(transform.eulerAngles.y, Vector3.up) * GetLinePosition(count * rayStep + rayStep) + ownPos; RaycastHit hitInfo; if (Physics.Linecast(startPos, endPos, out hitInfo)) { hitPoint = hitInfo.point; hitPos = (Quaternion.AngleAxis(360f - transform.eulerAngles.y, Vector3.up) * (hitPoint - ownPos)).z; Vector3 direc = Vector3.Normalize(hitPoint - CameraPos); float dis = Vector3.Distance(CameraPos, hitPoint) - 0.1f; if (!objMarkerImage.activeSelf && !Physics.Raycast(CameraPos, direc, dis)) objMarkerImage.SetActive(true); //if (!objMarkerImage.activeSelf) objMarkerImage.SetActive(true); break; } else { if (objMarkerImage.activeSelf) objMarkerImage.SetActive(false); } } //軌道予測線座標 for (int count = 0; count < lineDiv; count++) { Vector3 pos = GetLinePosition(count * lineStep); if (pos.z < hitPos) { Vector3 linePos = Quaternion.AngleAxis(transform.eulerAngles.y, Vector3.up) * pos + ownPos; linePosition.Add(linePos); } else { linePosition.Add(hitPoint); break; } } } if (Input.GetMouseButtonUp(0)) { rigBullet.useGravity = true; rigBullet.AddForce(transform.forward * shootPow, ForceMode.Impulse); shootPow = 0; objMarkerImage.SetActive(false); objLineRenderer.SetActive(false); uILine.SetVerticesDirty(); } private void LateUpdate() { //カメラの移動 if (Input.GetAxis("Mouse ScrollWheel") != 0) { cameraDis = Mathf.Clamp(cameraDis + Input.GetAxis("Mouse ScrollWheel") * 500f * Time.deltaTime, -3f, -0.2f); } Vector3 cameraPos = new Vector3(0.3f, 0.3f, cameraDis); cameraPos = Quaternion.AngleAxis(transform.eulerAngles.y, Vector3.up) * Quaternion.AngleAxis(transform.eulerAngles.x, Vector3.right) * cameraPos; objMainCamera.transform.position = cameraPos + transform.position; objMainCamera.transform.rotation = transform.rotation; uILine.Positions.Clear(); if (objMarkerImage.activeSelf) objMarkerImage.transform.position = RectTransformUtility.WorldToScreenPoint(mainCamera, hitPoint); if (linePosition.Count > 0) { for (int i = 0; i < linePosition.Count; i++) { uILine.Positions.Add(RectTransformUtility.WorldToScreenPoint(mainCamera, linePosition[i])); } uILine.SetVerticesDirty(); } } } |
実行結果
参考サイト
Unity – Unityで線を描画したい(109826)|teratail
uGUIで自由なメッシュを表示する(5.3統合版)
-
前の記事
衝突予測地点にマーカーを表示 2018.09.09
-
次の記事
端が直線にならないHPゲージの作り方 2018.09.16
コメントを書く