在右键 EasyTouch Controls-JoyStick 就会自动在 Hierarchy
层级面板自动生成一个 EasyTouchControlsCanvas和 InputManager
InputManager上面挂载着ETC Input的单例
ETC Input 里面 有几个字典成员axes 轴字典 controls 控制字典,管理 ETCbase
在EasyTouchControlsCanvas 下有个New Joystick 有时候按F2无法改名,需要在Inspect面板上的脚本上进行改名
下面是该类的类图
而Etc JoyStick 是继承自EtcBase的,以及几个 鼠标拖拽的接口, ETC Base这个 类十分重要, 有很多其他的Etc控制 脚本都是 继承自这个类的,
下面 是这个类,
using UnityEngine.UI;
using UnityEngine.Events;
using UnityEngine.EventSystems;
using System.Collections;
using System.Collections.Generic;
[System.Serializable]
public abstract class ETCBase : MonoBehaviour {
#region Enumeration
public enum ControlType {Joystick, TouchPad, DPad, Button};
public enum RectAnchor { UserDefined,BottomLeft,BottomCenter,BottonRight,CenterLeft,Center,CenterRight,TopLeft,TopCenter, TopRight};
public enum DPadAxis{ Two_Axis, Four_Axis };
public enum CameraMode{ Follow, SmoothFollow};
public enum CameraTargetMode{ UserDefined, LinkOnTag,FromDirectActionAxisX, FromDirectActionAxisY};
#endregion
#region Members
protected RectTransform cachedRectTransform;
protected Canvas cachedRootCanvas;
#region general propertie
public bool isUnregisterAtDisable = false;
private bool visibleAtStart = true;
private bool activatedAtStart = true;
[SerializeField]
protected RectAnchor _anchor;
public RectAnchor anchor {
get {
return _anchor;
}
set {
if (value != _anchor){
_anchor = value;
SetAnchorPosition();
}
}
}
[SerializeField]
protected Vector2 _anchorOffet;
public Vector2 anchorOffet {
get {
return _anchorOffet;
}
set {
if (value != _anchorOffet){
_anchorOffet = value;
SetAnchorPosition();
}
}
}
[SerializeField]
protected bool _visible;
public bool visible {
get {
return _visible;
}
set {
if (value != _visible){
_visible = value;
SetVisible();
}
}
}
[SerializeField]
protected bool _activated;
public bool activated {
get {
return _activated;
}
set {
if (value != _activated){
_activated = value;
SetActivated();
}
}
}
#endregion
#region Camera
public bool enableCamera=false;
public CameraMode cameraMode;
public string camTargetTag ="Player";
public bool autoLinkTagCam = true;
public string autoCamTag ="MainCamera";
public Transform cameraTransform;
public CameraTargetMode cameraTargetMode;
public bool enableWallDetection =false;
public LayerMask wallLayer = 0;
public Transform cameraLookAt;
protected CharacterController cameraLookAtCC;
public Vector3 followOffset = new Vector3(0,6,-6);
public float followDistance = 10;
public float followHeight = 5;
public float followRotationDamping=5;
public float followHeightDamping=5;
#endregion
#region Other
public int pointId=-1;
public bool enableKeySimulation; //允许 按键模拟
public bool allowSimulationStandalone; // 允许 独立平台 模拟
public bool visibleOnStandalone = true; //独立平台 可视
public DPadAxis dPadAxisCount;
public bool useFixedUpdate;
private List<RaycastResult> uiRaycastResultCache= new List<RaycastResult>();
private PointerEventData uiPointerEventData;
private EventSystem uiEventSystem;
public bool isOnDrag;
public bool isSwipeIn;
public bool isSwipeOut;
#endregion
#region Inspector
public bool showPSInspector;
public bool showSpriteInspector;
public bool showEventInspector;
public bool showBehaviourInspector;
public bool showAxesInspector;
public bool showTouchEventInspector;
public bool showDownEventInspector;
public bool showPressEventInspector;
public bool showCameraInspector;
#endregion
#endregion
#region Monobehaviour callback
protected virtual void Awake(){
cachedRectTransform = transform as RectTransform;
cachedRootCanvas = transform.parent.GetComponent<Canvas>();
#if (!UNITY_EDITOR)
if (!allowSimulationStandalone){
enableKeySimulation = false;
}
#endif
visibleAtStart = _visible;
activatedAtStart = _activated;
if (!isUnregisterAtDisable){
ETCInput.instance.RegisterControl( this);
}
}
public virtual void Start(){
if (enableCamera){
if (autoLinkTagCam){
cameraTransform = null;
GameObject tmpobj = GameObject.FindGameObjectWithTag(autoCamTag);
if (tmpobj){
cameraTransform = tmpobj.transform;
}
}
}
}
public virtual void OnEnable(){
if (isUnregisterAtDisable){
ETCInput.instance.RegisterControl( this);
}
visible = visibleAtStart;
activated = activatedAtStart;
}
void OnDisable(){
if (ETCInput._instance ){
if (isUnregisterAtDisable){
ETCInput.instance.UnRegisterControl( this );
}
}
visibleAtStart = _visible;
activated = _activated;
visible = false;
activated = false;
}
void OnDestroy(){
if (ETCInput._instance){
ETCInput.instance.UnRegisterControl( this );
}
}
public virtual void Update(){
if (!useFixedUpdate){
// StartCoroutine (UpdateVirtualControl());
DoActionBeforeEndOfFrame();
}
}
public virtual void FixedUpdate(){
if (useFixedUpdate){
//StartCoroutine (FixedUpdateVirtualControl());
DoActionBeforeEndOfFrame();
//UpdateControlState();
}
}
public virtual void LateUpdate(){
if (enableCamera){
// find camera
if (autoLinkTagCam && cameraTransform==null){
//cameraTransform = null;
GameObject tmpobj = GameObject.FindGameObjectWithTag(autoCamTag);
if (tmpobj){
cameraTransform = tmpobj.transform;
}
}
switch (cameraMode){
case CameraMode.Follow:
CameraFollow();
break;
case CameraMode.SmoothFollow:
CameraSmoothFollow();
break;
}
}
UpdateControlState();
}
#endregion
#region Virtual & public
protected virtual void UpdateControlState(){
}
protected virtual void SetVisible(bool forceUnvisible=true){
}
protected virtual void SetActivated(){
}
public void SetAnchorPosition(){
switch (_anchor){
case RectAnchor.TopLeft:
this.rectTransform().anchorMin = new Vector2(0,1);
this.rectTransform().anchorMax = new Vector2(0,1);
this.rectTransform().anchoredPosition = new Vector2( this.rectTransform().sizeDelta.x/2f + _anchorOffet.x, -this.rectTransform().sizeDelta.y/2f - _anchorOffet.y);
break;
case RectAnchor.TopCenter:
this.rectTransform().anchorMin = new Vector2(0.5f,1);
this.rectTransform().anchorMax = new Vector2(0.5f,1);
this.rectTransform().anchoredPosition = new Vector2( _anchorOffet.x, -this.rectTransform().sizeDelta.y/2f - _anchorOffet.y);
break;
case RectAnchor.TopRight:
this.rectTransform().anchorMin = new Vector2(1,1);
this.rectTransform().anchorMax = new Vector2(1,1);
this.rectTransform().anchoredPosition = new Vector2( -this.rectTransform().sizeDelta.x/2f - _anchorOffet.x, -this.rectTransform().sizeDelta.y/2f - _anchorOffet.y);
break;
case RectAnchor.CenterLeft:
this.rectTransform().anchorMin = new Vector2(0,0.5f);
this.rectTransform().anchorMax = new Vector2(0,0.5f);
this.rectTransform().anchoredPosition = new Vector2( this.rectTransform().sizeDelta.x/2f + _anchorOffet.x, _anchorOffet.y);
break;
case RectAnchor.Center:
this.rectTransform().anchorMin = new Vector2(0.5f,0.5f);
this.rectTransform().anchorMax = new Vector2(0.5f,0.5f);
this.rectTransform().anchoredPosition = new Vector2( _anchorOffet.x, _anchorOffet.y);
break;
case RectAnchor.CenterRight:
this.rectTransform().anchorMin = new Vector2(1,0.5f);
this.rectTransform().anchorMax = new Vector2(1,0.5f);
this.rectTransform().anchoredPosition = new Vector2( -this.rectTransform().sizeDelta.x/2f - _anchorOffet.x, _anchorOffet.y);
break;
case RectAnchor.BottomLeft:
this.rectTransform().anchorMin = new Vector2(0,0);
this.rectTransform().anchorMax = new Vector2(0,0);
this.rectTransform().anchoredPosition = new Vector2( this.rectTransform().sizeDelta.x/2f + _anchorOffet.x, this.rectTransform().sizeDelta.y/2f + _anchorOffet.y);
break;
case RectAnchor.BottomCenter:
this.rectTransform().anchorMin = new Vector2(0.5f,0);
this.rectTransform().anchorMax = new Vector2(0.5f,0);
this.rectTransform().anchoredPosition = new Vector2( _anchorOffet.x, this.rectTransform().sizeDelta.y/2f + _anchorOffet.y);
break;
case RectAnchor.BottonRight:
this.rectTransform().anchorMin = new Vector2(1,0);
this.rectTransform().anchorMax = new Vector2(1,0);
this.rectTransform().anchoredPosition = new Vector2( -this.rectTransform().sizeDelta.x/2f - _anchorOffet.x, this.rectTransform().sizeDelta.y/2f + _anchorOffet.y);
break;
}
}
protected GameObject GetFirstUIElement( Vector2 position){
uiEventSystem = EventSystem.current;
if (uiEventSystem != null){
uiPointerEventData = new PointerEventData( uiEventSystem);
uiPointerEventData.position = position;
uiEventSystem.RaycastAll( uiPointerEventData, uiRaycastResultCache);
if (uiRaycastResultCache.Count>0){
return uiRaycastResultCache[0].gameObject;
}
else{
return null;
}
}
else{
return null;
}
}
#endregion
#region Private Method
protected void CameraSmoothFollow(){
if (!cameraTransform || !cameraLookAt ) return ;
float wantedRotationAngle = cameraLookAt.eulerAngles.y;
float wantedHeight = cameraLookAt.position.y + followHeight;
float currentRotationAngle = cameraTransform.eulerAngles.y;
float currentHeight = cameraTransform.position.y;
currentRotationAngle = Mathf.LerpAngle(currentRotationAngle, wantedRotationAngle, followRotationDamping * Time.deltaTime);
currentHeight = Mathf.Lerp(currentHeight, wantedHeight, followHeightDamping * Time.deltaTime);
Quaternion currentRotation = Quaternion.Euler(0, currentRotationAngle, 0);
Vector3 newPos = cameraLookAt.position;
newPos -= currentRotation * Vector3.forward * followDistance;
newPos = new Vector3(newPos.x ,currentHeight , newPos.z);
if (enableWallDetection){
RaycastHit wallHit;
if (Physics.Linecast( new Vector3(cameraLookAt.position.x,cameraLookAt.position.y+1f,cameraLookAt.position.z),newPos, out wallHit)){
newPos= new Vector3( wallHit.point.x, currentHeight,wallHit.point.z);
}
}
cameraTransform.position = newPos;
cameraTransform.LookAt(cameraLookAt);
}
protected void CameraFollow(){
if (!cameraTransform || !cameraLookAt ) return ;
Vector3 localOffset = followOffset;
//if (cameraLookAtCC){
cameraTransform.position = cameraLookAt.position + localOffset;
cameraTransform.LookAt( cameraLookAt.position);
//}
//else{
//}
}
IEnumerator UpdateVirtualControl() {
DoActionBeforeEndOfFrame();
yield return new WaitForEndOfFrame();
UpdateControlState();
}
IEnumerator FixedUpdateVirtualControl() {
DoActionBeforeEndOfFrame();
yield return new WaitForFixedUpdate();
UpdateControlState();
}
protected virtual void DoActionBeforeEndOfFrame(){
}
#endregion
}
列举 类型,
#region Enumeration
public enum ControlType {Joystick, TouchPad, DPad, Button};
public enum RectAnchor { UserDefined,BottomLeft,BottomCenter,BottonRight,CenterLeft,Center,CenterRight,TopLeft,TopCenter, TopRight};
public enum DPadAxis{ Two_Axis, Four_Axis };
public enum CameraMode{ Follow, SmoothFollow};
public enum CameraTargetMode{ UserDefined, LinkOnTag,FromDirectActionAxisX, FromDirectActionAxisY};
#endregion
public enum ControlType {Joystick, TouchPad, DPad, Button}; 控制的类型,Joystick 虚拟 摇杆,
Joystick TouchPad 可能这样设置了 考虑到笔记本比较好用吧。
D Pad- Button
publi enum RectAnchor { UserDefined,BottomLeft,BottomCenter,BottonRight,CenterLeft,Center,CenterRight,TopLeft,TopCenter, TopRight}; RectAnchor 矩形锚点 :自定义,上 下左右中 等的 组合。
public enum DPadAxis{ Two_Axis, Four_Axis }; 两轴和四轴(拥有斜对角 两条斜轴)
public enum CameraMode{ Follow, SmoothFollow}; 摄像机模式 跟随和 平滑跟随
public enum CameraTargetMode{ UserDefined, LinkOnTag,FromDirectActionAxisX, FromDirectActionAxisY};
目标摄像机模式,自定义, 按Tag进行连接,方向X轴,方向Y轴
成员属性
#region Members
protected RectTransform cachedRectTransform;
protected Canvas cachedRootCanvas;
#region general propertie
public bool isUnregisterAtDisable = false;
private bool visibleAtStart = true;
private bool activatedAtStart = true;
[SerializeField]
protected RectAnchor _anchor;
public RectAnchor anchor {
get {
return _anchor;
}
set {
if (value != _anchor){
_anchor = value;
SetAnchorPosition();
}
}
}
[SerializeField]
protected Vector2 _anchorOffet;
public Vector2 anchorOffet {
get {
return _anchorOffet;
}
set {
if (value != _anchorOffet){
_anchorOffet = value;
SetAnchorPosition();
}
}
}
[SerializeField]
protected bool _visible;
public bool visible {
get {
return _visible;
}
set {
if (value != _visible){
_visible = value;
SetVisible();
}
}
}
[SerializeField]
protected bool _activated;
public bool activated {
get {
return _activated;
}
set {
if (value != _activated){
_activated = value;
SetActivated();
}
}
}
#endregion
#region Camera
public bool enableCamera=false;
public CameraMode cameraMode;
public string camTargetTag ="Player";
public bool autoLinkTagCam = true;
public string autoCamTag ="MainCamera";
public Transform cameraTransform;
public CameraTargetMode cameraTargetMode;
public bool enableWallDetection =false;
public LayerMask wallLayer = 0;
public Transform cameraLookAt;
protected CharacterController cameraLookAtCC;
public Vector3 followOffset = new Vector3(0,6,-6);
public float followDistance = 10;
public float followHeight = 5;
public float followRotationDamping=5;
public float followHeightDamping=5;
#endregion
#region Other
public int pointId=-1;
public bool enableKeySimulation;
public bool allowSimulationStandalone;
public bool visibleOnStandalone = true;
public DPadAxis dPadAxisCount;
public bool useFixedUpdate;
private List<RaycastResult> uiRaycastResultCache= new List<RaycastResult>();
private PointerEventData uiPointerEventData;
private EventSystem uiEventSystem;
public bool isOnDrag;
public bool isSwipeIn;
public bool isSwipeOut;
#endregion
#region Inspector
public bool showPSInspector;
public bool showSpriteInspector;
public bool showEventInspector;
public bool showBehaviourInspector;
public bool showAxesInspector;
public bool showTouchEventInspector;
public bool showDownEventInspector;
public bool showPressEventInspector;
public bool showCameraInspector;
#endregion
#endregion
protected RectTransform cachedRectTransform; 隐藏的 RectTransform
protected Canvas cachedRootCanvas; 隐藏的根Canvas.
public bool isUnregisterAtDisable = false; 是否 不注册时禁用
private bool visibleAtStart = true; 开始时是否可见
private bool activatedAtStart = true; 开始时启用
protected RectAnchor _anchor;
public RectAnchor anchor {
get {
return _anchor;
}
set {
if (value != _anchor){
_anchor = value;
SetAnchorPosition();
}
}
} RectAnchor 属性访问器 锚点方式
[SerializeField]
protected Vector2 _anchorOffet;
public Vector2 anchorOffet {
get {
return _anchorOffet;
}
set {
if (value != _anchorOffet){
_anchorOffet = value;
SetAnchorPosition();
}
}
} anchorOffet 属性访问器 锚点偏移
protected bool _visible;
public bool visible {
get {
return _visible;
}
set {
if (value != _visible){
_visible = value;
SetVisible();
}
}
} visible 属性访问器, 是否可见
[SerializeField]
protected bool _activated;
public bool activated {
get {
return _activated;
}
set {
if (value != _activated){
_activated = value;
SetActivated();
}
}
} activated 属性访问器, 是否活跃,
#region Camera 摄像机相关的 属性成员
public bool enableCamera=false; 是否启用摄像机
public CameraMode cameraMode; 摄像机模式。 跟随/平滑
public string camTargetTag ="Player"; 摄像机目标的标签 默认是 Player
public bool autoLinkTagCam = true; 自动连接标签摄像机
public string autoCamTag ="MainCamera"; 自动摄像机 的标签 默认 主摄像机
public Transform cameraTransform; 摄像机的Transform属性, 方便计算 平滑/跟随
public CameraTargetMode cameraTargetMode; 摄像机目标的模式 自定义, X方向, Y方向 , linkTag
public bool enableWallDetection =false; 是否 边界探测
public LayerMask wallLayer = 0; 边界的 层级
public Transform cameraLookAt; 摄像机 看向 的Transform
protected CharacterController cameraLookAtCC; 摄像机 看向 角色控制器
public Vector3 followOffset = new Vector3(0,6,-6); 跟随的 偏移
public float followDistance = 10; 跟随的 距离, // 感觉
public float followHeight = 5; //跟随高度
public float followRotationDamping=5;// 跟随旋转的衰减(缓冲)
public float followHeightDamping=5; //跟随高度的衰减
#endregion
#region Monobehaviour callback
//在Awake中 进行RecTransform的赋值,和Canvas的赋值,以及 在ETC input中 注册 控制事件监听
protected virtual void Awake(){
cachedRectTransform = transform as RectTransform;
cachedRootCanvas = transform.parent.GetComponent<Canvas>();
//编译指令 处理
#if (!UNITY_EDITOR)
if (!allowSimulationStandalone){
enableKeySimulation = false;
}
#endif
visibleAtStart = _visible;
activatedAtStart = _activated;
if (!isUnregisterAtDisable){
ETCInput.instance.RegisterControl( this);
}
}
//在start 中进行 摄像机的一些 查找赋值操作
public virtual void Start(){
if (enableCamera){
if (autoLinkTagCam){
cameraTransform = null;
GameObject tmpobj = GameObject.FindGameObjectWithTag(autoCamTag);
if (tmpobj){
cameraTransform = tmpobj.transform;
}
}
}
}
//在 Enable 中进行 注册 控制 事件 监听
public virtual void OnEnable(){
if (isUnregisterAtDisable){
ETCInput.instance.RegisterControl( this);
}
visible = visibleAtStart;
activated = activatedAtStart;
}
// 在 Disable 中 注销 控制 事件
void OnDisable(){
if (ETCInput._instance ){
if (isUnregisterAtDisable){
ETCInput.instance.UnRegisterControl( this );
}
}
visibleAtStart = _visible;
activated = _activated;
visible = false;
activated = false;
}
//在 Destroy 中 注销 控制 事件
void OnDestroy(){
if (ETCInput._instance){
ETCInput.instance.UnRegisterControl( this );
}
}
// 如果 不是使用FiexdUpdate, 在 UPdate 中 执行 DoActionBeforeEndOfFrame();是个空的方法,
//其他的类继承ETCbase时,要根据需求不同来实现此方法 做一些操作 在一针的结束前。
public virtual void Update(){
if (!useFixedUpdate){
// StartCoroutine (UpdateVirtualControl());
DoActionBeforeEndOfFrame();
}
}
// FiedUpdate, 如果useFiedUpdate的话 执行 DoActionBeforeEndOfFrame()
public virtual void FixedUpdate(){
if (useFixedUpdate){
//StartCoroutine (FixedUpdateVirtualControl());
DoActionBeforeEndOfFrame();
//UpdateControlState();
}
}
//LateUpdate 中 找到 摄像机, 并把位置信息更新,在根据 cameraMode 来进行 不同的 跟随方式
public virtual void LateUpdate(){
if (enableCamera){
// find camera
if (autoLinkTagCam && cameraTransform==null){
//cameraTransform = null;
GameObject tmpobj = GameObject.FindGameObjectWithTag(autoCamTag);
if (tmpobj){
cameraTransform = tmpobj.transform;
}
}
switch (cameraMode){
case CameraMode.Follow:
CameraFollow();
break;
case CameraMode.SmoothFollow:
CameraSmoothFollow();
break;
}
}
// 最后再 更新下 控制的状态
UpdateControlState();
}
#endregion
#region Virtual & public
protected virtual void UpdateControlState(){
}
//设置 可见
protected virtual void SetVisible(bool forceUnvisible=true){
}
//设置 活跃
protected virtual void SetActivated(){
}
//设置 锚点位置。 根据 _anchor的 不同来进行 计算
public void SetAnchorPosition(){
switch (_anchor){
case RectAnchor.TopLeft:
this.rectTransform().anchorMin = new Vector2(0,1);
this.rectTransform().anchorMax = new Vector2(0,1);
this.rectTransform().anchoredPosition = new Vector2( this.rectTransform().sizeDelta.x/2f + _anchorOffet.x, -this.rectTransform().sizeDelta.y/2f - _anchorOffet.y);
break;
case RectAnchor.TopCenter:
this.rectTransform().anchorMin = new Vector2(0.5f,1);
this.rectTransform().anchorMax = new Vector2(0.5f,1);
this.rectTransform().anchoredPosition = new Vector2( _anchorOffet.x, -this.rectTransform().sizeDelta.y/2f - _anchorOffet.y);
break;
case RectAnchor.TopRight:
this.rectTransform().anchorMin = new Vector2(1,1);
this.rectTransform().anchorMax = new Vector2(1,1);
this.rectTransform().anchoredPosition = new Vector2( -this.rectTransform().sizeDelta.x/2f - _anchorOffet.x, -this.rectTransform().sizeDelta.y/2f - _anchorOffet.y);
break;
case RectAnchor.CenterLeft:
this.rectTransform().anchorMin = new Vector2(0,0.5f);
this.rectTransform().anchorMax = new Vector2(0,0.5f);
this.rectTransform().anchoredPosition = new Vector2( this.rectTransform().sizeDelta.x/2f + _anchorOffet.x, _anchorOffet.y);
break;
case RectAnchor.Center:
this.rectTransform().anchorMin = new Vector2(0.5f,0.5f);
this.rectTransform().anchorMax = new Vector2(0.5f,0.5f);
this.rectTransform().anchoredPosition = new Vector2( _anchorOffet.x, _anchorOffet.y);
break;
case RectAnchor.CenterRight:
this.rectTransform().anchorMin = new Vector2(1,0.5f);
this.rectTransform().anchorMax = new Vector2(1,0.5f);
this.rectTransform().anchoredPosition = new Vector2( -this.rectTransform().sizeDelta.x/2f - _anchorOffet.x, _anchorOffet.y);
break;
case RectAnchor.BottomLeft:
this.rectTransform().anchorMin = new Vector2(0,0);
this.rectTransform().anchorMax = new Vector2(0,0);
this.rectTransform().anchoredPosition = new Vector2( this.rectTransform().sizeDelta.x/2f + _anchorOffet.x, this.rectTransform().sizeDelta.y/2f + _anchorOffet.y);
break;
case RectAnchor.BottomCenter:
this.rectTransform().anchorMin = new Vector2(0.5f,0);
this.rectTransform().anchorMax = new Vector2(0.5f,0);
this.rectTransform().anchoredPosition = new Vector2( _anchorOffet.x, this.rectTransform().sizeDelta.y/2f + _anchorOffet.y);
break;
case RectAnchor.BottonRight:
this.rectTransform().anchorMin = new Vector2(1,0);
this.rectTransform().anchorMax = new Vector2(1,0);
this.rectTransform().anchoredPosition = new Vector2( -this.rectTransform().sizeDelta.x/2f - _anchorOffet.x, this.rectTransform().sizeDelta.y/2f + _anchorOffet.y);
break;
}
}
//在 uiRaycastResultCache中 查找 返回 用RaycastAll()方法
protected GameObject GetFirstUIElement( Vector2 position){
uiEventSystem = EventSystem.current;
if (uiEventSystem != null){
uiPointerEventData = new PointerEventData( uiEventSystem);
uiPointerEventData.position = position;
uiEventSystem.RaycastAll( uiPointerEventData, uiRaycastResultCache);
if (uiRaycastResultCache.Count>0){
return uiRaycastResultCache[0].gameObject;
}
else{
return null;
}
}
else{
return null;
}
}
#endregion
#region Private Method
// 摄像机平滑跟随
protected void CameraSmoothFollow(){
if (!cameraTransform || !cameraLookAt ) return ;
float wantedRotationAngle = cameraLookAt.eulerAngles.y;
float wantedHeight = cameraLookAt.position.y + followHeight;
float currentRotationAngle = cameraTransform.eulerAngles.y;
float currentHeight = cameraTransform.position.y;
// 用插值 来进行计算
currentRotationAngle = Mathf.LerpAngle(currentRotationAngle, wantedRotationAngle, followRotationDamping * Time.deltaTime);
currentHeight = Mathf.Lerp(currentHeight, wantedHeight, followHeightDamping * Time.deltaTime);
//再转换为 欧拉角
Quaternion currentRotation = Quaternion.Euler(0, currentRotationAngle, 0);
Vector3 newPos = cameraLookAt.position;
newPos -= currentRotation * Vector3.forward * followDistance;
newPos = new Vector3(newPos.x ,currentHeight , newPos.z);
if (enableWallDetection){
RaycastHit wallHit;
// 线性 投射 从开始位置到结束位置做一个光线投射,如果与碰撞体交互,返回真。 可以根据Layer mask层的不同来忽略碰撞体。
if (Physics.Linecast( new Vector3(cameraLookAt.position.x,cameraLookAt.position.y+1f,cameraLookAt.position.z),newPos, out wallHit)){
newPos= new Vector3( wallHit.point.x, currentHeight,wallHit.point.z);
}
}
cameraTransform.position = newPos;
cameraTransform.LookAt(cameraLookAt);
}
//摄像机 跟随
protected void CameraFollow(){
if (!cameraTransform || !cameraLookAt ) return ;
Vector3 localOffset = followOffset;
//if (cameraLookAtCC){
cameraTransform.position = cameraLookAt.position + localOffset;
cameraTransform.LookAt( cameraLookAt.position);
//}
//else{
//}
}
// 更新虚拟控制的 协程
IEnumerator UpdateVirtualControl() {
DoActionBeforeEndOfFrame();
yield return new WaitForEndOfFrame(); //一针后 再 更新 控制状态
UpdateControlState();
}
// 固定 更新虚拟控制
IEnumerator FixedUpdateVirtualControl() {
DoActionBeforeEndOfFrame();
yield return new WaitForFixedUpdate();
UpdateControlState();
}
//空方法 , 一针结束前要做的东东
protected virtual void DoActionBeforeEndOfFrame(){
}
#endregion