using UnityEngine; using System.Collections; using System.Collections.Generic; using Thousandto.Core.Base; public class MoveCameraByPath : MonoBehaviour { // 内部变量 Vector3 m_startPos = Vector3.zero; Quaternion m_startQuatern = Quaternion.identity; Vector3 m_lastPos = Vector3.zero; Vector3 m_curPos = Vector3.zero; float m_startTime = 0.0f; float m_viewTime = 20.0f; bool m_showGUI = true; bool m_start = false; private bool adjustViewDirAuto = true; private int m_curIndex = 0; private iTweenPathEX m_curmovePath; private iTweenPathEX m_curviewPath; // 外部变量 public List<iTweenPathEX> movePaths = new List<iTweenPathEX>(); public List<iTweenPathEX> viewPaths = new List<iTweenPathEX>(); // Use this for initialization void Start() { m_startPos = transform.position; m_startQuatern = transform.rotation; m_showGUI = true; } // Update is called once per frame void Update() { if ( m_start ) { m_curPos = transform.position; if ( adjustViewDirAuto ) { if ( m_curPos != m_lastPos ) { UpdateDirection( m_curPos - m_lastPos ); } } else { // 使用两个曲线描述观察者相机 if ( m_curviewPath != null ) { transform.LookAt( m_curviewPath.gameObject.transform ); } } m_lastPos = m_curPos; if ( !m_showGUI ) { if ( Time.time - m_startTime > m_viewTime ) { if ( movePaths.Count > m_curIndex ) { m_showGUI = false; iTween.Stop(); StartCoroutine( WaitFrameToDo( 1, ( _str ) => { if ( GetCurrentCurve( out m_curmovePath, out m_curviewPath ) ) { InitRunTime(); RunViewCam( m_curmovePath, m_curviewPath ); } else { Debug.LogError( "没有设置相机移动曲线" ); m_showGUI = true; StopViewCam(); } } ) ); } else { m_showGUI = true; StopViewCam(); } } } } } void OnGUI() { if ( m_showGUI ) { if ( GUI.Button( new Rect( 10, 10, 150, 80 ), "Run Camera" ) ) { if ( GetCurrentCurve( out m_curmovePath, out m_curviewPath ) ) { InitRunTime(); RunViewCam( m_curmovePath, m_curviewPath ); m_showGUI = false; } else { Debug.LogError( "没有设置相机移动曲线" ); } } } } #region 主要功能 public void InitRunTime() { if ( m_curmovePath != null ) { m_viewTime = m_curmovePath.totalePlayTime; if ( m_curviewPath != null ) { m_viewTime = Mathf.Max( m_curmovePath.totalePlayTime, m_curviewPath.totalePlayTime ); } } } public void InitCurve( iTweenPathEX tagPath ) { if ( tagPath == null ) { return; } if ( !iTweenPath.paths.ContainsKey( tagPath.pathName ) ) { iTweenPath.paths.Add( tagPath.pathName.ToLower(), tagPath ); } } // 使用曲线开始移动相机以及调整视线 public void RunViewCam( iTweenPathEX movePath, iTweenPathEX viewPath ) { InitCurve( movePath ); InitCurve( viewPath ); iTweenPathEX pathComponent = movePath; if ( pathComponent != null ) { var path = iTweenPath.GetPath( pathComponent.pathName ); if ( path != null ) { transform.position = path[0]; m_curPos = transform.position; m_lastPos = m_curPos; iTween.MoveTo( gameObject, iTween.Hash( "position", transform, "path", path, "time", pathComponent.totalePlayTime, "easetype", "linear" ) ); // settings m_showGUI = false; } } iTweenPathEX viewComponent = viewPath; if ( viewComponent != null ) { var path = iTweenPath.GetPath( viewComponent.pathName ); if ( path != null ) { viewComponent.gameObject.transform.position = path[0]; iTween.MoveTo( viewComponent.gameObject, iTween.Hash( "path", path, "time", viewComponent.totalePlayTime, "easetype", "linear" ) ); } } m_startTime = Time.time; m_start = true; //Debug.LogWarning( "Start Curve : " + pathComponent.name + " Time : " + m_startTime.ToString() ); } // 停止播放, 返回最初位置 public void StopViewCam() { iTween.Stop(); iTweenPath.paths.Clear(); m_start = false; m_curIndex = 0; transform.position = m_startPos; transform.rotation = m_startQuatern; } #endregion #region Help Funcs // 自动转动镜头 void UpdateDirection( Vector3 dir ) { transform.rotation = Quaternion.LookRotation( dir ); } // 获取下一个相机曲线 bool GetCurrentCurve( out iTweenPathEX movePath, out iTweenPathEX viewPath ) { movePath = movePaths[m_curIndex]; viewPath = viewPaths[m_curIndex]; if ( movePath != null ) { // 当使用自动调整时不需要视线曲线 adjustViewDirAuto = movePath.adjustViewDirAuto; if ( adjustViewDirAuto || viewPath != null ) { m_curIndex++; return true; } } return false; } // 等待曲线END -- 在同一帧内的顶点会自动合并为曲线顶点 IEnumerator WaitFrameToDo(int frames = 1, MyAction<string> func = null) { for ( int i = 0; i < frames; i++ ) { yield return new WaitForEndOfFrame(); } if ( func != null ) { func( "test" ); } } #endregion }