Unity 常用工具方法拓展
阿新 • • 發佈:2018-12-17
using DG.Tweening; using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.Events; using UnityEngine.PostProcessing; using UnityEngine.UI; public enum RenderingMode { Opaque, Cutout, Fade, Transparent, } public static class MyUtilities { #region Animation private static Dictionary<Animation, bool> bool_Animation = new Dictionary<Animation, bool>(); public static void DetectionAnimation(this Animation ani, string animationName, UnityAction OnStart, UnityAction OnUpdate, UnityAction OnEnd) { if (!bool_Animation.ContainsKey(ani)) { bool_Animation.Add(ani, false); } if (!bool_Animation[ani]) { if (ani.IsPlaying(animationName)) { bool_Animation[ani] = true; OnStart(); } } else { if (ani.IsPlaying(animationName)) { OnUpdate(); } else { OnEnd(); bool_Animation.Remove(ani); } } } /// <summary> /// 根據進度播放動畫 /// </summary> /// <param name="ani"></param> /// <param name="aniName">動畫名稱</param> /// <param name="progress">進度</param> public static void PlayAnimationFollowProgress(this Animation ani,string aniName,float progress) { AnimationState state = ani[aniName]; state.normalizedTime = progress; state.normalizedSpeed = 0; ani.Play(aniName); } public static IEnumerator IEDetectionAnimation(this Animation ani, string animationName, UnityAction OnStart, UnityAction OnUpdate, UnityAction OnEnd) { while (!ani.IsPlaying(animationName)) { yield return null; } OnStart(); while (ani.IsPlaying(animationName)) { OnUpdate(); yield return null; } OnEnd(); } /// <summary> /// 倒播動畫 /// </summary> /// <param name="ani"></param> /// <param name="aniName"></param> /// <param name="OnStart"></param> /// <param name="OnUpdate"></param> /// <param name="OnEnd"></param> /// <returns></returns> public static IEnumerator IEBackPlayAnimation(this Animation ani, string aniName, UnityAction OnStart = null, UnityAction OnUpdate = null, UnityAction OnEnd = null) { if (ani == null) yield break; ani[aniName].speed = -1; ani[aniName].time = ani[aniName].length; ani.Play(aniName); if (OnStart != null) { OnStart(); } while (ani.IsPlaying(aniName)) { if (OnUpdate != null) { OnUpdate(); } yield return null; } ani[aniName].speed = 1; if (OnEnd != null) { OnEnd(); } } /// <summary> /// 正播動畫 /// </summary> /// <param name="ani"></param> /// <param name="aniName"></param> /// <param name="OnStart"></param> /// <param name="OnUpdate"></param> /// <param name="OnEnd"></param> /// <returns></returns> public static IEnumerator IEForwardPlayAnimation(this Animation ani, string aniName, UnityAction OnStart = null, UnityAction OnUpdate = null, UnityAction OnEnd = null) { if (ani == null) yield break; if (ani.IsPlaying(aniName)) yield break; ani[aniName].speed = 1; ani.Play(aniName); if (OnStart != null) { OnStart(); } while (ani.IsPlaying(aniName)) { if (OnUpdate != null) { OnUpdate(); } yield return null; } if (OnEnd != null) { OnEnd(); } } #endregion #region Animator private static Dictionary<Animator, bool> bool_Animator = new Dictionary<Animator, bool>(); public static void DetectionAnimator(this Animator ani, int layerIndex, string stateName, UnityAction OnStart, UnityAction OnUpdate, UnityAction OnEnd) { if (!bool_Animator.ContainsKey(ani)) { bool_Animator.Add(ani, false); } if (!bool_Animator[ani]) { if (ani.GetCurrentAnimatorStateInfo(layerIndex).IsName(stateName)) { bool_Animator[ani] = true; OnStart(); } } else { if (ani.GetCurrentAnimatorStateInfo(layerIndex).IsName(stateName)) { OnUpdate(); } else { bool_Animator[ani] = false; OnEnd(); } } } public static void ResetBool_Animator() { if (bool_Animator != null) bool_Animator.Clear(); } public static IEnumerator IEDetectionAnimator(this Animator ani, int layerIndex, string stateName, UnityAction OnStart, UnityAction OnUpdate, UnityAction OnEnd) { while (!ani.GetCurrentAnimatorStateInfo(layerIndex).IsName(stateName)) { yield return null; } OnStart(); while (ani.GetCurrentAnimatorStateInfo(layerIndex).IsName(stateName)) { OnUpdate(); yield return null; } OnEnd(); } #endregion #region GameObject/Transform public static string GetParentPath(this Transform target) { string path = ""; while (target.parent != null) { if (path != "") { path = "/" + path; } path = target.parent.name + path; target = target.parent; } return path; } // public static Sequence mySequence; // public static bool isMoving = false; public static void DoMoveAndRotation(this GameObject target, Vector3 position, Vector3 rotation, float duration, Ease ease, UnityAction OnUpdate, UnityAction OnEnd, Space spaceWorld = Space.Self) { if (target.GetComponent<WowMainCamera>()) { if (target.GetComponent<WowMainCamera>().enabled) { // print("存在WowMainCamera.cs指令碼"); Debug.LogError("存在WowMainCamera.cs指令碼"); return; } } // isMoving = true; // mySequence.Kill(); Sequence mySequence = DOTween.Sequence(); mySequence.SetId("DoMoveAndRotation"); Tweener t1; Tweener t2; switch (spaceWorld) { case Space.Self: t1 = target.transform.DOLocalMove(position, duration).SetEase(ease); t2 = target.transform.DOLocalRotate(rotation, duration).SetEase(ease); break; default: t1 = target.transform.DOMove(position, duration).SetEase(ease); t2 = target.transform.DORotate(rotation, duration).SetEase(ease); break; } // mySequence = DOTween.Sequence(); mySequence.Append(t1) .Insert(0, t2) .AppendCallback(() => { // isMoving = false; OnEnd(); }).OnUpdate(() => { OnUpdate(); }); } public static Sequence SharkSequence; public static void Shake(this GameObject target, float time, Vector3 strengthV3, bool isCamera, UnityAction OnUpdate) { SharkSequence.Kill(); Tweener t1; if (isCamera) t1 = target.transform.DOShakeRotation(time, strengthV3, 0, 0); else t1 = target.transform.DOShakePosition(time, strengthV3, 0, 0); SharkSequence = DOTween.Sequence(); SharkSequence.SetId("Shake"); SharkSequence.Append(t1); } public static void Swing(this GameObject target, float time, Vector3 strengthV3, UnityAction OnUpdate) { if (SharkSequence == null || !SharkSequence.IsActive()) { SharkSequence.Kill(); Tweener t1 = target.transform.DOShakeRotation(time, strengthV3, 0, 0); SharkSequence = DOTween.Sequence(); SharkSequence.SetId("Swing"); SharkSequence.Append(t1); } } public static void WowSetControl(this GameObject target, bool isControl, bool isDrag, bool isZoom) //改變WowMainCamera的CanBeControl和canBeZoom變數 { WowMainCamera wow = target.GetComponent<WowMainCamera>(); if (wow == null) { Debug.LogError("wow為null"); return; } wow.allowDrag = isDrag; wow.allowControl = isControl; wow.allowZoom = isZoom; } public static void WowDoMove_X_Y_Distance(this GameObject target, Vector3 position, float x, float y, float distance, float duration, Ease ease, UnityAction OnUpdate, UnityAction OnEnd, Space spaceWorld = Space.Self) { // isMoving = true; // mySequence.Kill(); WowMainCamera wow = target.GetComponent<WowMainCamera>(); if (wow == null) { Debug.LogError("wow為null"); return; } Tweener t1, t2, t3, t4; wow.x %= 360; wow.y %= 360; float deviation = Mathf.Abs(wow.x - x); if (deviation > 180) { if (x > 0) { if (wow.x > 180) { x += 360; } else { x -= 360; } } else { if (wow.x < -180) { wow.x += 360; } else { x += 360; } } } switch (spaceWorld) { case Space.Self: t1 = wow.target.transform.DOLocalMove(position, duration).SetEase(ease); break; default: t1 = wow.target.transform.DOMove(position, duration).SetEase(ease); break; } t2 = DOTween.To(() => wow.x, a => wow.x = a, x, duration).SetEase(ease); t4 = DOTween.To(() => wow.y, b => wow.y = b, y, duration).SetEase(ease); t3 = DOTween.To(() => wow.desiredDistance, c => wow.desiredDistance = c, distance, duration).SetEase(Ease.Linear); Sequence mySequence = DOTween.Sequence(); mySequence.SetId("WowDoMove_X_Y_Distance"); mySequence.Append(t1) .Insert(0, t2) .Insert(0, t3) .Insert(0, t4) .AppendCallback(() => { // isMoving = false; OnEnd(); }).OnUpdate(() => { OnUpdate(); }); } public static void WowDoMove(this GameObject target, Vector3 position, float duration, Ease ease, UnityAction OnUpdate, UnityAction OnEnd, Space spaceWorld = Space.Self) { // isMoving = true; // mySequence.Kill(); WowMainCamera wow = target.GetComponent<WowMainCamera>(); if (wow == null) { Debug.LogError("wow為null"); return; } Tweener t1; switch (spaceWorld) { case Space.Self: t1 = wow.target.transform.DOLocalMove(position, duration).SetEase(ease); break; default: t1 = wow.target.transform.DOMove(position, duration).SetEase(ease); break; } Sequence mySequence = DOTween.Sequence(); mySequence.SetId("WowDoMove"); mySequence.Append(t1) .AppendCallback(() => { // isMoving = false; OnEnd(); }).OnUpdate(() => { OnUpdate(); }); } public static void WowDoXY(this GameObject target, float x, float y, float duration, Ease ease, UnityAction OnUpdate, UnityAction OnEnd) { // isMoving = true; // mySequence.Kill(); WowMainCamera wow = target.GetComponent<WowMainCamera>(); if (wow == null) { Debug.LogError("wow為null"); return; } wow.x %= 360; wow.y %= 360; float deviation = Mathf.Abs(wow.x - x); if (deviation > 180) { if (x > 0) { if (wow.x > 180) { x += 360; } else { x -= 360; } } else { if (wow.x < -180) { wow.x += 360; } else { x += 360; } } } Tweener t2 = DOTween.To(() => wow.x, a => wow.x = a, x, duration).SetEase(ease); Tweener t4 = DOTween.To(() => wow.y, b => wow.y = b, y, duration).SetEase(ease); Sequence mySequence = DOTween.Sequence(); mySequence.SetId("WowDoXY"); mySequence.Append(t2) .Insert(0, t4) .AppendCallback(() => { // isMoving = false; OnEnd(); }).OnUpdate(() => { OnUpdate(); }); } public static void WowDoMove_X_Y(this GameObject target, Vector3 position, float x, float y, float duration, Ease ease, UnityAction OnUpdate, UnityAction OnEnd, Space worldSpace = Space.Self) { // isMoving = true; // mySequence.Kill(); WowMainCamera wow = target.GetComponent<WowMainCamera>(); if (wow == null) { Debug.LogError("wow為null"); return; } Tweener t1; switch (worldSpace) { case Space.Self: t1 = wow.target.transform.DOLocalMove(position, duration).SetEase(ease); break; default: t1 = wow.target.transform.DOMove(position, duration).SetEase(ease); break; } wow.x %= 360; wow.y %= 360; float deviation = Mathf.Abs(wow.x - x); if (deviation > 180) { if (x > 0) { if (wow.x > 180) { x += 360; } else { x -= 360; } } else { if (wow.x < -180) { wow.x += 360; } else { x += 360; } } } Tweener t2 = DOTween.To(() => wow.x, a => wow.x = a, x, duration).SetEase(ease); Tweener t4 = DOTween.To(() => wow.y, b => wow.y = b, y, duration).SetEase(ease); Sequence mySequence = DOTween.Sequence(); mySequence.SetId("WowDoMove_X_Y"); mySequence.Append(t1) .Insert(0, t2) .Insert(0, t4) .AppendCallback(() => { // isMoving = false; OnEnd(); }).OnUpdate(() => { OnUpdate(); }); } public static void WowDoDistance(this GameObject target, float distance, float duration, Ease ease, UnityAction OnUpdate, UnityAction OnEnd) { // isMoving = true; // mySequence.Kill(); WowMainCamera wow = target.GetComponent<WowMainCamera>(); if (wow == null) { Debug.LogError("wow為null"); return; } Tweener t3 = DOTween.To(() => wow.desiredDistance, c => wow.desiredDistance = c, distance, duration).SetEase(Ease.Linear); Sequence mySequence = DOTween.Sequence(); mySequence.SetId("WowDoDistance"); mySequence.Append(t3) .AppendCallback(() => { // isMoving = false; OnEnd(); }).OnUpdate(() => { OnUpdate(); }); } #endregion #region Graphic #region Text // public static Sequence sequence_text; public static Dictionary<Text, Sequence> text_Sequence = new Dictionary<Text, Sequence>(); public static void FadeShowText(this Text text, float showtime, string text_str, Color text_color) { Sequence sequence_text = null; Debug.Log(text_Sequence.ContainsKey(text) + " " + text_Sequence.Count + " " + text.name); if (text_Sequence.ContainsKey(text)) { sequence_text = text_Sequence[text]; sequence_text.Kill(true); sequence_text = DOTween.Sequence(); text_Sequence.Remove(text); text_Sequence.Add(text, sequence_text); } else { sequence_text = DOTween.Sequence(); text_Sequence.Add(text, sequence_text); } text.text = text_str; text.color = new Color(text_color.r, text_color.g, text_color.b, 0); Tweener t1 = text.DOFade(1, 1); Tweener t2 = text.DOFade(0, 1); sequence_text.SetId("FadeShowText"); sequence_text.Append(t1) .AppendInterval(showtime) .Append(t2) .OnComplete(() => { text_Sequence.Remove(text); Debug.Log("remove"); }); } #endregion public static Dictionary<Graphic, Sequence> graphic_Sequence = new Dictionary<Graphic, Sequence>(); public static void FadeInOut(this Graphic graphic, float time_stay, UnityAction OnFadeIn, UnityAction OnEnd) { Tweener t1 = graphic.DOFade(1, 0.8f).OnComplete(() => { OnFadeIn(); }); Tweener t2 = graphic.DOFade(0, 0.8f).SetDelay(time_stay).OnComplete(() => { graphic_Sequence.Remove(graphic); OnEnd(); }); Sequence sequence = null; if (graphic_Sequence.ContainsKey(graphic)) { sequence = graphic_Sequence[graphic]; sequence.Kill(true); } //else //{ sequence = DOTween.Sequence(); sequence.SetId("FadeInOut"); graphic_Sequence.Add(graphic, sequence); //} sequence.Append(t1) .AppendInterval(time_stay) .Append(t2) .AppendCallback(() => { graphic_Sequence.Remove(graphic); Debug.Log("remove"); }); } #endregion #region Camera public static void DoCameraMoveRotationAndView(this Camera ca, Vector3 position, Vector3 rotation, float view, float duration, Ease ease, UnityAction OnUpdate, UnityAction OnEnd) { if (ca.GetComponent<WowMainCamera>()) { if (ca.GetComponent<WowMainCamera>().enabled) { // print("存在WowMainCamera.cs指令碼"); Debug.LogError("存在WowMainCamera.cs指令碼"); return; } } Sequence mySequence = DOTween.Sequence(); mySequence.SetId("DoCameraMoveRotationAndView"); Tweener t1 = ca.transform.DOMove(position, duration).SetEase(ease); Tweener t2 = ca.transform.DORotate(rotation, duration).SetEase(ease); Tweener t3 = ca.DOFieldOfView(view, duration).SetEase(ease); mySequence.Append(t1) .Insert(0, t2) .Insert(0, t3) .AppendCallback(() => { //isMoving = false; OnEnd(); }).OnUpdate(() => { OnUpdate(); }); } #endregion #region MonoBehaviour public static void DelayToDo(this MonoBehaviour m, float time, UnityAction method) { float a = 0; Tweener t = DOTween.To(() => { return a; }, (v) => { a = v; }, 10, time).OnComplete(() => { method(); }); t.SetId("DelayToDo"); } public static bool IsMasterOrIsUnline(this MonoBehaviour m) { if ((PhotonNetwork.connected && PhotonNetwork.isMasterClient) || RPCUtilities.Instance.isUnLineTest) { return true; } else { return false; } } #endregion #region GameObject public static GameObject GetGameObject(this ScriptableObject m, string path) { return GameObjectCachePool.Instance.getGameObject(path); } public static GameObject GetGameObject(this GameObject m, string path) { return GameObjectCachePool.Instance.getGameObject(path); } public static GameObject GetGameObject(this MonoBehaviour m, string path) { return GameObjectCachePool.Instance.getGameObject(path); } public static void ChangeChildrenTag(this Transform m, string tagName) { if (m == null) return; m.tag = tagName; for (int i = 0; i < m.childCount; i++) { m.GetChild(i).tag = tagName; ChangeChildrenTag(m.GetChild(i), tagName); } } #endregion #region Transform public enum FrontPostionEnum { Top,//預設向上轉25度 Center,//預設0度 Bottom//預設向下轉25度 } /// <summary> /// 得到物體前方N米的位置 不跟隨transform.forward /// </summary> /// <param name="t"></param> /// <param name="frontDis">前方距離</param> /// <param name="offset">偏移量,360°,可調節</param> /// <returns>返回物體的世界座標</returns> public static Vector3 FrontPosition(this Transform t, float frontDis, float offset = 0) { Vector3 resultV = Vector3.zero; resultV = t.position + t.forward * frontDis; resultV = new Vector3(resultV.x, t.position.y, resultV.z); //前方向量 Vector3 v = (resultV - t.position).normalized; //v的垂直向量 Vector3 v2 = Quaternion.AngleAxis(90, Vector3.up) * v; //旋轉offset後的向量 Vector3 v3 = Quaternion.AngleAxis(offset, v2) * v; //位置+向量*距離 resultV = t.position + v3 * frontDis; return resultV; } /// <summary> /// 得到物體前方N米的位置 跟隨transform.forward /// </summary> /// <param name="t"></param> /// <param name="frontDis">前方距離</param> /// <param name="frontPositionEnum">位置列舉,上方,中間,下方</param> /// <param name="offset">偏移量,360°,可調節</param> /// <returns>返回物體的世界座標</returns> public static Vector3 FrontPosition(this Transform t, float frontDis, FrontPostionEnum frontPositionEnum, float offset = 0) { Vector3 resultV = Vector3.zero; switch (frontPositionEnum) { case FrontPostionEnum.Top: resultV = t.position + Quaternion.AngleAxis(offset - 25.0f, t.right) * t.forward * frontDis; break; case FrontPostionEnum.Center: resultV = t.position + Quaternion.AngleAxis(offset, t.right) * t.forward * frontDis; break; case FrontPostionEnum.Bottom: resultV = t.position + Quaternion.AngleAxis(offset + 25.0f, t.right) * t.forward * frontDis; break; } return resultV; } #endregion #region Material public static void SetMaterialRenderingMode(Material material, RenderingMode renderingMode) { switch (renderingMode) { case RenderingMode.Opaque: material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One); material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero); material.SetInt("_ZWrite", 1); material.DisableKeyword("_ALPHATEST_ON"); material.DisableKeyword("_ALPHABLEND_ON"); material.DisableKeyword("_ALPHAPREMULTIPLY_ON"); material.renderQueue = -1; break; case RenderingMode.Cutout: material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One); material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero); material.SetInt("_ZWrite", 1); material.EnableKeyword("_ALPHATEST_ON"); material.DisableKeyword("_ALPHABLEND_ON"); material.DisableKeyword("_ALPHAPREMULTIPLY_ON"); material.renderQueue = 2450; break; case RenderingMode.Fade: material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha); material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha); material.SetInt("_ZWrite", 0); material.DisableKeyword("_ALPHATEST_ON"); material.EnableKeyword("_ALPHABLEND_ON"); material.DisableKeyword("_ALPHAPREMULTIPLY_ON"); material.renderQueue = 3000; break; case RenderingMode.Transparent: material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One); material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha); material.SetInt("_ZWrite", 0); material.DisableKeyword("_ALPHATEST_ON"); material.DisableKeyword("_ALPHABLEND_ON"); material.EnableKeyword("_ALPHAPREMULTIPLY_ON"); material.renderQueue = 3000; break; } } public static void SetTransplant(this Transform target, RenderingMode renderingMode, float apha, bool changeChild) { if (target.GetComponent<Renderer>()) { for (int i = 0; i < target.GetComponent<Renderer>().materials.Length; i++) { target.GetComponent<Renderer>().materials[i].color = new Color(target.GetComponent<Renderer>().materials[i].color.r, target.GetComponent<Renderer>().materials[i].color.g, target.GetComponent<Renderer>().materials[i].color.b, apha); SetMaterialRenderingMode(target.GetComponent<Renderer>().materials[i], renderingMode); } } if (changeChild) { for (int i = 0; i < target.childCount; i++) { SetTransplant(target.GetChild(i), renderingMode, apha, true); } } } public static void SetTransplant(Transform target, RenderingMode renderingMode, float apha, float time, bool changeChild) { if (target.GetComponent<Renderer>()) { for (int i = 0; i < target.GetComponent<Renderer>().materials.Length; i++) { SetMaterialRenderingMode(target.GetComponent<Renderer>().materials[i], renderingMode); target.GetComponent<Renderer>().materials[i].DOColor(new Color(target.GetComponent<Renderer>().materials[i].color.r, target.GetComponent<Renderer>().materials[i].color.g, target.GetComponent<Renderer>().materials[i].color.b, apha), time); } } if (changeChild) { for (int i = 0; i < target.childCount; i++) { SetTransplant(target.GetChild(i), renderingMode, apha, time, true); } } } public static void SetTransplant(this Transform target, RenderingMode renderingMode, float apha, float time, bool changeChild, UnityAction method) { if (target.GetComponent<Renderer>()) { for (int i = 0; i < target.GetComponent<Renderer>().materials.Length; i++) { target.GetComponent<Renderer>().materials[i].DOColor(new Color(target.GetComponent<Renderer>().materials[i].color.r, target.GetComponent<Renderer>().materials[i].color.g, target.GetComponent<Renderer>().materials[i].color.b, apha), time); SetMaterialRenderingMode(target.GetComponent<Renderer>().materials[i], renderingMode); } } if (changeChild) { for (int i = 0; i < target.childCount; i++) { SetTransplant(target.GetChild(i), renderingMode, apha, time, true); } } DelayToDo(time, method); } #endregion public static void DelayToDo(float time, UnityAction method) { //Time.timeScale = float a = 0; Tweener t = DOTween.To(() => { return a; }, (v) => { a = v; }, 10, time).OnComplete(() => { method(); }); t.SetId("DelayToDo"); } public static void DelayToDo(float time, string Id, UnityAction method) { //Time.timeScale = float a = 0; Tweener t = DOTween.To(() => { return a; }, (v) => { a = v; }, 10, time).OnComplete(() => { method(); }); t.SetId(Id); } } public static class Mathf_Frame { /// <summary> /// 計算直線和麵的交點 /// </summary> /// <param name="planeVector">平面的法向量</param> /// <param name="planePoint">平面上一點</param> /// <param name="lineVector">直線的方向向量</param> /// <param name="linePoint">直線上一點</param> /// <returns></returns> public static Vector3 CalPlaneLineIntersectPoint(Vector3 planeVector, Vector3 planePoint, Vector3 lineVector, Vector3 linePoint) { Vector3 returnResult = Vector3.zero; float vp1, vp2, vp3, n1, n2, n3, v1, v2, v3, m1, m2, m3, t, vpt; vp1 = planeVector.x; vp2 = planeVector.y; vp3 = planeVector.z; n1 = planePoint.x; n2 = planePoint.y; n3 = planePoint.z; v1 = lineVector.x; v2 = lineVector.y; v3 = lineVector.z; m1 = linePoint.x; m2 = linePoint.y; m3 = linePoint.z; vpt = v1 * vp1 + v2 * vp2 + v3 * vp3; //首先判斷直線是否與平面平行 if (vpt == 0) { // returnResult = null; Debug.Log("無交點"); } else { t = ((n1 - m1) * vp1 + (n2 - m2) * vp2 + (n3 - m3) * vp3) / vpt; returnResult.x = m1 + v1 * t; returnResult.y = m2 + v2 * t; returnResult.z = m3 + v3 * t; } return returnResult; } }