Ai
1 Star 6 Fork 1

dante/UnityGlobalFuncs

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
MyInput.cs 41.23 KB
一键复制 编辑 原始数据 按行查看 历史
dante 提交于 2019-03-18 22:35 +08:00 . PC 时也有冻结某个按键的效果
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291
using UnityEngine;
using System.Collections;
using UnityEngine.EventSystems;
using UnityEngine.UI;
using System;
using UnityEngine.Events;
using Game.UI;
using Game.Global.Helper;
using System.Collections.Generic;
/// <summary>
/// 自定义的触摸屏操作:
/// 给定移动范围、在移动范围内操作摇杆图片,并更新CrossPlatformInput的轴向值
/// (如果不Attach到物体上,则只有鼠标输入可获取,如果需要虚拟Pad,请Attach到虚拟摇杆触点子物体中)
/// </summary>
public class MyInput : MonoBehaviour, IPointerDownHandler, IPointerUpHandler, IDragHandler
{
//--------------------------------------------------------------------------------------------------------------
//------------------------------------------------公用静态函数------------------------------------------------
//--------------------------------------------------------------------------------------------------------------
#region 静态部分
#region --虚拟摇杆以及按钮事件
/// <summary>
/// 不分左右Shift:是否按着shift
/// </summary>
public static bool IsShiftHold()
{
return Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift);
}
/// <summary>
/// 不分左右:是否按着Alt
/// </summary>
public static bool IsAltHold()
{
return Input.GetKey(KeyCode.LeftAlt) || Input.GetKey(KeyCode.RightAlt);
}
/// <summary>
/// 不分左右:是否按着Clt
/// </summary>
public static bool IsCltHold()
{
return Input.GetKey(KeyCode.LeftControl) || Input.GetKey(KeyCode.RightControl);
}
public static float GetVerticalAxis()
{
#if UNITY_EDITOR || UNITY_STANDALONE
//PC 下,则尝试尝试键盘的咯
if (!isAnyVirtualAxisDown)
{
//尝试获取键盘的:
axisVector.y = Input.GetAxis("Vertical");
}
#endif
return axisVector.y;
}
public static float GetHorizontalAxis()
{
#if UNITY_EDITOR || UNITY_STANDALONE
//PC 下,还可尝试尝试键盘输入
if (!isAnyVirtualAxisDown)
{
//尝试获取键盘的:
axisVector.x = Input.GetAxis("Horizontal");
}
#endif
return axisVector.x;
}
/// <summary>
/// 是否有移动的按键按下(WASD或者摇杆)
/// </summary>
/// <returns></returns>
public static bool IsAnyAxisChange()
{
#if UNITY_EDITOR|| UNITY_STANDALONE
if (Math.Abs(GetHorizontalAxis()) > 0.1f || Math.Abs(GetVerticalAxis()) > 0.1f)
{
return true;
}
#endif
//探测是否按下了虚拟摇杆
return isAnyVirtualAxisDown;
}
/// <summary>
/// 是否有任何接触或者按键
/// </summary>
/// <returns></returns>
public static bool IsAnyTouch()
{
#if UNITY_EDITOR|| UNITY_STANDALONE
if (Input.anyKey)
{
return true;
}
#endif
return Input.touchCount > 0;
}
static Vector3[] m_lastPCMousePoses = new Vector3[3];
[System.Obsolete("弃用此方法,应该不需要如此之多")]
//PC端的中键移动
/// <summary>
/// PC:获得拖动移动范围
/// </summary>
/// <param name="mouseBt">哪个按键</param>
/// <returns></returns>
public static Vector3 GetMouseDelta(int mouseBt = 2)
{
if (Input.GetMouseButtonDown(mouseBt))
{
m_lastPCMousePoses[mouseBt] = mousePosition;
return Vector3.zero;
}
else if (Input.GetMouseButton(mouseBt))
{
Vector2 delta = m_lastPCMousePoses[mouseBt] - mousePosition;
m_lastPCMousePoses[mouseBt] = mousePosition;
return delta;
}
else
{
return Vector3.zero;
}
}
/// <summary>
/// 获得方向上的移动(如WASD、或者虚拟摇杆)
/// </summary>
public static Vector2 GetMoveAxis()
{
//PC下:
#if UNITY_EDITOR|| UNITY_STANDALONE
//没按下虚拟摇杆:
if (!isAnyVirtualAxisDown)
{
//尝试获得WASD移动方向:
GetHorizontalAxis();
GetVerticalAxis();
}
#endif
return axisVector;
}
[System.Obsolete()]
/// <summary>
/// 释放所有可按下的功能键
/// </summary>
public static void ReleaseFunctionKeys()
{
//释放所有锁定(直到获取时才被重置)的bool键:
isJumpButtonDown = false;
isAttackButtonDown = false;
isThrowButtonDown = false;
}
/// <summary>
/// 重置摇杆数据
/// </summary>
public static void ResetAxis()
{
axisVector = Vector2.zero;
}
/// <summary>
/// 设置MyInput Canvas(需已经实例化)下的对应按钮及其功能
/// </summary>
/// <param name="buttonName">对应按钮名称</param>
/// <param name="onButtonClick">点击时发生的事件</param>
public static void SetButtonFunction(string buttonName, CallbackFunc onButtonClick)
{
SetButtonFunction(buttonName, onButtonClick, null, null);
}
/// <summary>
/// 设置MyInput Canvas(需已经实例化)下的对应按钮及其功能
/// </summary>
/// <param name="buttonName">对应按钮名称</param>
/// <param name="onButtonDown">当按钮按下时的触发事件</param>
/// <param name="onButtonUp">当按钮释放的事件</param>
public static void SetButtonFunction(string buttonName, CallbackFunc onButtonDown, CallbackFunc onButtonUp)
{
SetButtonFunction(buttonName, null, onButtonDown, onButtonUp);
}
/// <summary>
/// 设置MyInput Canvas(需已经实例化)下的对应按钮及其功能
/// </summary>
/// <param name="buttonName">对应按钮名称</param>
/// <param name="onButtonClick">点击时发生的事件</param>
/// <param name="onButtonDown">当按钮按下时的触发事件</param>
/// <param name="onButtonUp">当按钮释放的事件</param>
public static void SetButtonFunction(string buttonName, CallbackFunc onButtonClick, CallbackFunc onButtonDown, CallbackFunc onButtonUp)
{
if (g_instance == null)
{
Debug.LogWarning("No MyInput instance.");
return;
}
var canvas = g_instance.GetComponentInParent<Canvas>();
if (canvas == null)
{
Debug.LogWarning("No canvas set or it is hidden.");
return;
}
Transform canvasTrans = canvas.transform;
//获得按钮
var btnTrans = canvasTrans.GetChildByName(buttonName);
if (btnTrans == null)
{
Debug.LogWarning("Cannot find button[" + buttonName + "] in " + canvasTrans.name + " to bind the function.");
return;
}
SetButtonFunction(btnTrans, onButtonClick, onButtonDown, onButtonUp);
}
public static void SetButtonFunction(Transform btnTrans, CallbackFunc onButtonClick, CallbackFunc onButtonDown, CallbackFunc onButtonUp)
{
if (btnTrans == null)
{
Debug.LogWarning("Cannot bind a null button with function.");
return;
}
var btn = btnTrans.GetComponent<GameUIClickable>();
if (btn == null)
{
btn = btnTrans.gameObject.AddComponent<GameUIClickable>();
}
//--添加对应的行为回调
btn.SetOnClickListener(onButtonClick, onButtonDown, onButtonUp);
}
#region 不推荐使用的仿GetKeyGetKeyDown,方法在PC | 移动端(需要有对应Canvas和调用AwakeButton)有效
static bool[] m_isKeysDown = new bool[14]; //是否按下,默认最多14键
static bool[] m_isKeysOn = new bool[14]; //是否按住,默认最多14键
static bool[] m_isKeysFreeze = new bool[14];
static bool m_clearKeysAfterFrame; //是否有任一按键按下,是的话将在帧结束后清除标记
static Dictionary<int, KeyCode> m_customToPCKeyCode = null;
/// <summary>
/// 批量设置枚举之中的所有KeyCode对应的按钮功能,按下时可以通过GetButtonDown访问(会清除其他类设置的按键)
/// <para>注意:必须存在MyInput所属的Canvas,且按键在Canvas之中,且按键的Button名称与之相同</para>
/// </summary>
/// <typeparam name="T">需要的KeyCode枚举</typeparam>
/// <param name="enumCount">如果有Count的枚举,则填入其值,并跳过该按钮及其以后的设置</param>
public static void InitKeyCodeFunction<T>(int enumCount = -1) where T : struct, IConvertible
{
InitKeyCodeFunction<T>(new Dictionary<string, string>(), enumCount);
}
/// <summary>
/// 批量设置MyInput的画布中,按枚举指定的所有按钮功能,按下时可以通过GetButtonDown访问(会清除其他类设置的按键)
/// <para>注意:必须存在MyInput所属的Canvas,且按键在Canvas之中</para>
/// </summary>
/// <param name="keyCodeToBtnNameDict">额外指定 KeyCode键-映射到按钮上的名称,则会将该按钮视作某个KeyCode</param>
/// <typeparam name="T">需要的KeyCode枚举</typeparam>
/// <param name="enumCount">如果有Count的枚举,则填入其值,跳过该按钮及其以后的设置</param>
public static void InitKeyCodeFunction<T>(Dictionary<string, string> keyCodeToBtnNameDict, int enumCount = -1) where T : struct, IConvertible
{
InitKeyCodeFunction<T>(null, keyCodeToBtnNameDict, enumCount);
}
/// <summary>
/// 批量设置枚举之中的所有按钮功能,按下时可以通过GetButtonDown访问(会清除其他类设置的按键)
/// <para>不要求按键在Input所属的Canvas中</para>
/// </summary>
/// <param name="keyCodeToBtnDict">额外指定 KeyCode键-映射到按钮上的名称,则会将该按钮视作某个KeyCode</param>
/// <typeparam name="T">需要的KeyCode枚举</typeparam>
/// <param name="enumCount">如果有Count的枚举,则填入其值,跳过该按钮及其以后的设置</param>
public static void InitKeyCodeFunction<T>(Dictionary<string, RectTransform> keyCodeToBtnDict, int enumCount = -1) where T : struct, IConvertible
{
InitKeyCodeFunction<T>(keyCodeToBtnDict, null, enumCount);
}
/// <summary>
/// 批量设置枚举之中的所有按钮功能,按下时可以通过GetButtonDown访问(会清除其他类设置的按键)
/// <para>注意:必须存在MyInput所属的Canvas,且按键在Canvas之中</para>
/// </summary>
/// <param name="keyCodeToBtnNameDict">额外指定 KeyCode键-映射到按钮上的名称,则会将该按钮视作某个KeyCode</param>
/// <typeparam name="T">需要的KeyCode枚举</typeparam>
/// <param name="enumCount">如果有Count的枚举,则填入其值,跳过该按钮及其以后的设置</param>
private static void InitKeyCodeFunction<T>(Dictionary<string, RectTransform> keyCodeToBtnDict, Dictionary<string, string> keyCodeToBtnNameDict, int enumCount = -1) where T : struct, IConvertible
{
//Get Enums:
Array keyEnums = Enum.GetValues(typeof(T));
//Generate booleans
int keyCodesCount = enumCount > 0 ? enumCount : keyEnums.Length;
m_isKeysDown = new bool[keyCodesCount];
m_isKeysOn = new bool[keyCodesCount];
m_isKeysFreeze = new bool[keyCodesCount];
bool hasKeyCodeToNameDict = GameObjFunc.HasItems(keyCodeToBtnNameDict);
bool hasKeyCodeToBtnDict = GameObjFunc.HasItems(keyCodeToBtnDict);
foreach (var keyCodeInfo in keyEnums)
{
int keyCodeIndex = (int)keyCodeInfo;
if (enumCount > 0)
{
//Skip the COUNT Enum if exist
if (keyCodeIndex >= enumCount)
{
continue;
}
}
//Find the key button & set the function
string keyButtonName = keyCodeInfo.ToString();
if (hasKeyCodeToNameDict && keyCodeToBtnNameDict.ContainsKey(keyButtonName))
{
//指定名称的情况:指定了某个按键对应的按钮名称,则使用映射的按钮名称:
ReBindButtonToKeyCode(keyCodeToBtnNameDict[keyButtonName], keyCodeIndex);
}
else if (!hasKeyCodeToNameDict && keyCodeToBtnDict.ContainsKey(keyButtonName))
{
//直接绑定按键,而不是指定名称:
ReBindButtonToKeyCode(keyCodeToBtnDict[keyButtonName], keyCodeIndex); ;
}
else
{
//默认则绑定KeyCode指定的按钮名称:
ReBindButtonToKeyCode(keyButtonName, keyCodeIndex);
}
}
}
/// <summary>
/// 直接指定自定义的KeyCode与PC键盘的KeyCode关系(不一定需要KeyCode相同)
/// </summary>
/// <param name="keyCodeToCustomKeyCodes">Key code to custom key codes.</param>
public static void BindPCKeyCodeToCustomKeyCode(Dictionary<KeyCode, Enum> keyCodeToCustomKeyCodes)
{
if (GameObjFunc.HasItems(keyCodeToCustomKeyCodes))
{
if (m_customToPCKeyCode == null)
{
m_customToPCKeyCode = new Dictionary<int, KeyCode>();
}
foreach (var pcToCustomKeyIndexer in keyCodeToCustomKeyCodes)
{
int customKeyValue = Convert.ToInt32(pcToCustomKeyIndexer.Value);
m_customToPCKeyCode[customKeyValue] = pcToCustomKeyIndexer.Key;
}
}
}
/// <summary>
/// 重设MyInput 的Canvas中的某个button对应的keycode 及其回调
/// </summary>
/// <param name="keyButtonName">Key button name.</param>
/// <param name="keyCodeIndex">Key code index.</param>
/// <param name="onKeyDown">On key down.</param>
/// <param name="onKeyUp">On key up.</param>
public static void ReBindButtonToKeyCode(string keyButtonName, int keyCodeIndex, CallbackFunc onKeyDown = null, CallbackFunc onKeyUp = null)
{
ReBindButtonToKeyCode(null, keyButtonName, keyCodeIndex, onKeyDown, onKeyUp);
}
/// <summary>
/// 重设某个button对应的keycode 及其回调
/// </summary>
/// <param name="keyButtonTrans">Key button transform.</param>
/// <param name="keyCodeIndex">Key code index.</param>
/// <param name="onKeyDown">On key down.</param>
/// <param name="onKeyUp">On key up.</param>
public static void ReBindButtonToKeyCode(RectTransform keyButtonTrans, int keyCodeIndex, CallbackFunc onKeyDown = null, CallbackFunc onKeyUp = null)
{
ReBindButtonToKeyCode(keyButtonTrans, null, keyCodeIndex, onKeyDown, onKeyUp);
}
/// <summary>
/// 重设某个button对应的keycode 及其回调
/// </summary>
/// <param name="keyButtonTrans">Key button Trans.</param>
/// <param name="keyButtonName">Button name</param>
/// <param name="keyCodeIndex">Key code index.</param>
/// <param name="onKeyDown">On key down.</param>
/// <param name="onKeyUp">On key up.</param>
private static void ReBindButtonToKeyCode(RectTransform keyButtonTrans, string keyButtonName, int keyCodeIndex, CallbackFunc onKeyDown = null, CallbackFunc onKeyUp = null)
{
#if UNITY_EDITOR
if (keyCodeIndex > m_isKeysDown.Length)
{
throw new NotImplementedException("Use Enums that defined by yourself instead,Current keycode value:" + keyCodeIndex);
}
#endif
//创建回调:
CallbackFunc onDown =
() =>
{
m_isKeysDown[keyCodeIndex] = true;
m_isKeysOn[keyCodeIndex] = true;
//标记在帧结束后,需要做好清除Down标记工作:
m_clearKeysAfterFrame = true;
if (onKeyDown != null)
{
onKeyDown();
}
};
CallbackFunc onUp = () =>
{
m_isKeysDown[keyCodeIndex] = false;
m_isKeysOn[keyCodeIndex] = false;
if (onKeyUp != null)
{
onKeyUp();
}
};
//绑定事件
//--是指定RectTransform的:
if (keyButtonTrans != null)
{
SetButtonFunction(keyButtonTrans, null, onDown, onUp);
}
else
{
//否则是指定Button名称的:
SetButtonFunction(keyButtonName, null, onDown, onUp);
}
}
/// <summary>
/// 锁定/解锁某个按键,使之按下无效
/// </summary>
/// <param name="selfKeyCodeEnum">Self key code enum.</param>
/// <param name="isLock">是否锁定该按键</param>
public static void SetButtonLock(Enum selfKeyCodeEnum,bool isLock)
{
m_isKeysFreeze[Convert.ToInt32(selfKeyCodeEnum)] = isLock;
}
/// <summary>
/// 按键按下?(注意:不要使用KeyCode,而使用自定义的Code。且必须场景中存在MyInput所属的Canvas并执行Awake以唤醒按钮功能)
/// </summary>
/// <param name="selfDefinedKeyCode">自行定义的KeyCode,不要使用KeyCode</param>
/// <returns></returns>
public static bool GetButtonDown(Enum selfDefinedKeyCode)
{
#if UNITY_EDITOR
if (selfDefinedKeyCode is KeyCode)
{
throw new NotImplementedException("Use Enums that defined by yourself instead");
}
#endif
int keyIndex = Convert.ToInt32(selfDefinedKeyCode);
//Console.WriteLine("Key index:" + keyIndex);
if (m_isKeysDown[keyIndex]
&& !m_isKeysFreeze[keyIndex])
{
return true;
}
#if UNITY_EDITOR || UNITY_STANDALONE
return TryGetPCKey(selfDefinedKeyCode, false);
#endif
return false;
}
/// <summary>
/// Is button Pressing? (注意:必须场景中存在MyInput所属的Canvas并执行Awake以唤醒按钮功能)
/// </summary>
/// <param name="keyCode"></param>
/// <returns></returns>
public static bool GetButton(Enum keyCode)
{
int keyIndex = Convert.ToInt32(keyCode);
if (m_isKeysOn[keyIndex]
&& !m_isKeysFreeze[keyIndex])
{
return true;
}
#if UNITY_EDITOR || UNITY_STANDALONE
TryGetPCKey(keyCode, true);
#endif
return false;
}
/// <summary>
/// 尝试从自定义的按键,指定为PC键盘的输入
/// </summary>
/// <returns><c>true</c>, if get PCK ey was tryed, <c>false</c> otherwise.</returns>
/// <param name="selfDefinedKeyCode">Self defined key code.</param>
/// <param name="isHolding">If set to <c>true</c> is holding.</param>
private static bool TryGetPCKey(Enum selfDefinedKeyCode, bool isHolding)
{
int keyIndex = Convert.ToInt32(selfDefinedKeyCode);
if(m_isKeysFreeze[keyIndex])
{
return false;
}
bool gotKey = false;
KeyCode pcKey;
if (TryParse<KeyCode>(selfDefinedKeyCode.ToString(), out pcKey))
{
gotKey = true;
}
else
{
if (GameObjFunc.HasItems(m_customToPCKeyCode))
{
int custKeyVal = Convert.ToInt32(selfDefinedKeyCode);
if (m_customToPCKeyCode.TryGetValue(custKeyVal, out pcKey))
{
gotKey = true;
}
}
}
if (gotKey)
{
if (isHolding)
{
return Input.GetKey(pcKey);
}
else
{
return Input.GetKeyDown(pcKey);
}
}
return false;
}
/// <summary>
/// 帧结束后清除KeyDown标记
/// </summary>
private void ClearKeysFlag()
{
for (int i = 0; i < m_isKeysDown.Length; i++)
{
m_isKeysDown[i] = false;
}
}
/// <summary>
/// 尝试转换Enum,2.0的mscorlib似乎缺少此方法,补之
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="strEnumCode"></param>
/// <returns></returns>
private static bool TryParse<T>(string strEnumCode, out T enumCode)
{
object pcKeyCode = null;
try
{
pcKeyCode = Enum.Parse(typeof(KeyCode), strEnumCode);
}
catch
{
pcKeyCode = null;
}
enumCode = default(T);
if (pcKeyCode != null)
{
enumCode = (T)pcKeyCode;
return true;
}
else
{
return false;
}
}
#endregion
#region PC Only
#if UNITY_STANDALONE || UNITY_EDITOR
/// <summary>
/// 常见的游戏按钮
/// </summary>
public enum GameKey
{
/// <summary>
/// 水平方向
/// </summary>
Horizontal,
/// <summary>
/// 竖直方向
/// </summary>
Vertical,
/// <summary>
/// 跳
/// </summary>
Jump,
/// <summary>
/// 攻击
/// </summary>
Attack,
/// <summary>
/// 攻击2
/// </summary>
Attack2,
/// <summary>
/// 攻击3
/// </summary>
Attack3,
/// <summary>
/// 加速跑
/// </summary>
Trot,
/// <summary>
/// 互动
/// </summary>
Interact,
}
/// <summary>
/// PC Only:Unity预制按键是否正按住
/// </summary>
/// <param name="gameKey"></param>
/// <returns></returns>
public static bool PCGetButton(GameKey gameKey)
{
return Input.GetButton(gameKey.ToString());
}
/// <summary>
/// Unity预制按键是否Down
/// </summary>
/// <param name="gameKey"></param>
/// <returns></returns>
public static bool PCGetButtonDown(GameKey gameKey)
{
return Input.GetButtonDown(gameKey.ToString());
}
/// <summary>
/// Unity预制按键是否Up
/// </summary>
/// <param name="gameKey"></param>
/// <returns></returns>
public static bool PCGetButtonUp(GameKey gameKey)
{
return Input.GetButtonUp(gameKey.ToString());
}
#endif
#endregion
/// <summary>
/// 获得MyInput所在的Canvas下指定UI物体组件
/// </summary>
/// <typeparam name="T">UI物体组件</typeparam>
/// <param name="uiName">该组件名</param>
/// <returns></returns>
public static T GetUIObject<T>(string uiName)
{
return g_instance.GetComponentInParent<Canvas>()
.transform.GetChildByName<T>(uiName);
}
#endregion
#region --鼠标或者Touch输入
//--预判用--:#if UNITY_EDITOR || UNITY_STANDALONE
public static int touchCount
{
get
{
#if UNITY_EDITOR || UNITY_STANDALONE
return GetMouse() ? 1 : 0;//唯有1与0
#else
return Input.touchCount;
#endif
}
}
/// <summary>
/// 触摸或鼠标左键正在按住
/// </summary>
public static bool GetMouse(int pcMouseId = 0)
{
#if UNITY_EDITOR || UNITY_STANDALONE
return Input.GetMouseButton(pcMouseId);
#else
return Input.touchCount > 0;
#endif
}
/// <summary>
/// 触摸或鼠标按下。(默认鼠标判断左键)
/// </summary>
/// <param name="pcMouseId">0=左键,1=右键,2=中键.仅对PC有效,对于触控时无参数影响</param>
public static bool GetMouseDown(int pcMouseId = 0)
{
#if UNITY_EDITOR || UNITY_STANDALONE
return Input.GetMouseButtonDown(pcMouseId);
#else
if (Input.touchCount > 0 && Input.GetTouch(0).phase == TouchPhase.Began)
{
return true;
}
return false;
#endif
}
/// <summary>
/// 触摸或鼠标按下
/// </summary>
/// <param name="pcMouseId">0=左键,1=右键,2=中键.对于触控时无参数影响</param>
public static bool GetMouseUp(int pcMouseId = 0)
{
#if UNITY_EDITOR || UNITY_STANDALONE
return Input.GetMouseButtonUp(pcMouseId);
#else
if (Input.touchCount > 0 && Input.GetTouch(0).phase == TouchPhase.Ended)
{
return true;
}
return false;
#endif
}
static Vector2 mouseClickPos;
static bool hasClickedDown = false;
/// <summary>
/// 查看是否发生了单击行为(在同一个点按下和释放鼠标/触摸)
/// </summary>
public static bool GetMouseClick(int pcMouseId = 0)
{
//还未点击,现在点击了
if (!hasClickedDown)
{
if (GetMouseDown(pcMouseId))
{
hasClickedDown = true;
mouseClickPos = mousePosition;
}
}
else//ClickDowned,now try to get up
if (GetMouseUp(pcMouseId))
{
//--前后差距足够小,即为在该点点击
Vector2 currPos = mousePosition;
if (Vector2.SqrMagnitude(currPos - mouseClickPos) < 1)
{
return true;
}
hasClickedDown = false;
}
return false;
}
static float lastClickTime = -1;
/// <summary>
/// 查看是否发生了第二次点击后的长按行为(在同一个点两次按下后不释放鼠标)
/// </summary>
public static bool GetMouseDoubleHold(int pcMouseId = 0)
{
//第一次的按下
if (GetMouseClick(pcMouseId))
{
lastClickTime = Time.time;
return false;
}
//如果是第二次按下(需要综合上次点击时间考虑)
else if (GetMouseDown(pcMouseId)
&& Time.time - lastClickTime < 0.3f)
{
Debug.Log("DDDDD");
lastClickTime = -1;
return true;
}
return false;
}
/// <summary>
/// 判断是否在UI上,但是反之不定在游戏物体上;
/// </summary>
/// <returns></returns>
public static bool IsMouseOnUI()
{
#if UNITY_EDITOR
if (EventSystem.current == null)
{
Debug.LogError("No eventSystem found.");
return false;
}
#endif
if (
#if UNITY_STANDALONE || UNITY_EDITOR
EventSystem.current.IsPointerOverGameObject() == false//false即为在物体上而非UI上
#else
Input.touchCount==1
&& EventSystem.current.IsPointerOverGameObject(0) == false//false即为在物体上而非UI上
#endif
)
{
//并不在UI上
return false;
}
else
{
return true;
}
}
[System.Obsolete("USE IsMouseOnObj() instead.")]
/// <summary>
/// 获得在鼠标位置的obj,弃用
/// </summary>
/// <seealso cref="IsMouseOnObj"/>
public static bool GetObjOnMouse(out Transform obj)
{
return IsMouseOnObj(out obj);
}
/// <summary>
/// 获得鼠标/触摸(不指定是否按下) 当前所指向的物体
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
public static bool IsMouseOnObj(out Transform obj)
{
RaycastHit hit;
if (IsMouseOnObj(out hit))
{
obj = hit.transform;
return true;
}
else
{
obj = null;
return false;
}
}
/// <summary>
/// 判断当前鼠标(不指定是否按下)是否在游戏物体上。无则为Null, 否则返回碰撞消息
/// </summary>
public static bool IsMouseOnObj(out RaycastHit hit)
{
// if (
// #if UNITY_STANDALONE || UNITY_EDITOR
// EventSystem.current.IsPointerOverGameObject() == false//false即为非UI
// #else
// Input.touchCount==1
// && EventSystem.current.IsPointerOverGameObject(0) == false//false即为非UI
// #endif
// )
// {
Camera cam = Camera.main;
Ray ray = cam.ScreenPointToRay(mousePosition);
//直接返回是否在物体上,以及对应的碰撞信息
return (Physics.Raycast(ray, out hit));
// }
// else
// {
// //在ui上:
// return false;
// }
}
/// <summary>
/// 获得触摸或鼠标位置
/// </summary>
public static Vector3 mousePosition
{
get
{
#if UNITY_EDITOR || UNITY_STANDALONE
return Input.mousePosition;
#else
if (Input.touchCount > 0)
return Input.GetTouch(0).position;
else return Vector3.zero;
#endif
}
}
#region 移动端缩放/移动空白地方操作的静态函数
static float m_moveViewSpeed = 600F;
static Vector2 currTouchPos = Vector2.zero; //当前触摸/鼠标的位置
static Vector2 lastTouchPos = Vector2.zero; //上一次鼠标/触摸的位置
static Vector2 secTouchLastTouchPos = Vector2.zero; //第二根手指头的上一轮的位置
/// <summary>
/// PC Only:是否移动了视图(PC:鼠标右键/中键移动),返回时间间隔内偏移值。
/// (直接使用GetMouseDragDelta)
/// <para>PS:必须在Update中被调用,才能获得移动偏移值</para>
/// </summary>
/// <param name="moveViewDelta">前后移动的差值</param>
/// <param name="minDelta">最小偏移值,避免抖动</param>
/// <returns>是否移动了</returns>
public static bool IsMouseDragDelta(out Vector2 moveViewDelta, float minDelta = 1)
{
return GetMouseDragDelta(out moveViewDelta, minDelta);
}
/// <summary>
/// Mouse或Touch是否拖动了,返回时间间隔内偏移值(大于阙值)。
/// <para>PS:必须在Update中被调用,才能获得移动偏移值</para>
/// </summary>
/// <param name="dragDelta">前后移动的差值</param>
/// <param name="minDelta">最小偏移值,避免抖动</param>
/// <param name="mouseId">检查的鼠标/触控ID</param>
/// <returns>是否移动了</returns>
public static bool GetMouseDragDelta(out Vector2 dragDelta, float minDelta = 1, int mouseId = 0)
{
dragDelta = Vector2.zero;
//第一次的按下
if (GetMouseDown(mouseId))
{
lastTouchPos = MyInput.mousePosition;
//返回无位置移动
return false;
}
else if (GetMouse(mouseId)) //按下且拖拽
{
//获得距离差:
Vector2 mousePos = MyInput.mousePosition;
dragDelta = lastTouchPos - mousePos;
if (dragDelta.SqrMagnitude() > minDelta) //达到预定范围,则取此偏移值并返回
{
//接受此次的距离差
lastTouchPos = mousePos;
return true;
}
}
return false;
}
//#if MOBILE_INPUT
private static bool beginDragScale = false; //用于标记第一帧开始控制时
private static float lastTouchDistance = 0; //上一帧间的拖拽距离
private static float distanceNoiseDelta = 64; //距离噪点64pixel以内,拒绝抖动
private static bool m_acceptControll = false; //是否接受控制
/// <summary>
/// 提供判断触摸屏两指缩放操作:返回为是否有两指拖拽操作
/// </summary>
/// <param name="scaleFactor">两指拖拽的距离差</param>
/// <returns>是否有两指拖拽操作</returns>
public static bool HasScrollViewOp(out float scaleFactor)
{
scaleFactor = 0;
#if UNITY_STANDALONE || UNITY_EDITOR
if (EventSystem.current.IsPointerOverGameObject() == false)
{
//PC时,通过滚轮取得缩放值
scaleFactor = Input.mouseScrollDelta.y * 3;
return Mathf.Abs(scaleFactor) > 0.1F;
}
else
{
return false;
}
#elif MOBILE_INPUT
//Mobile时,通过两根手指间的缩放距离取得缩放:
if (Input.touchCount > 0 && Input.GetTouch(0).phase == TouchPhase.Began)
{
//开始按下的刹那
if (EventSystem.current.IsPointerOverGameObject(0) == false)
{
//若是指尖触及
m_acceptControll = true; //Not UI
}
else
{
//还是彷徨
m_acceptControll = false; //Touching UI
return false;
}
}
if (m_acceptControll && Input.touchCount >= 2)
{
#region 指间拖拽了那时轻狂
if (!beginDragScale)
{
//The first status: Record the touches
lastTouchDistance = Vector2.Distance(
Input.GetTouch(0).position, Input.GetTouch(1).position); //Sqrt of Magnitude
beginDragScale = true;
}
else
{
//Draging...This is Next Frame:
float currDistance = Vector2.Distance(
Input.GetTouch(0).position, Input.GetTouch(1).position); //Sqrt of Magnitude
float delta = currDistance - lastTouchDistance;
if (Mathf.Abs(delta) > distanceNoiseDelta)
{
//Accept change:
scaleFactor = delta*0.1F;
//Recaculate next.
lastTouchDistance = currDistance;
return true;
}
}
#endregion
}
else
{
//却放纵了韶华
beginDragScale = false;
}
return false;
#endif
}
//#endif
#endregion
#endregion
#endregion
//--------------------------------------------------------------------------------------------------------------
// 实例操作部分
//
//--------------------------------------------------------------------------------------------------------------
#region --虚拟摇杆用数据--
//--虚拟按键中的ID配置用
[SerializeField] string m_btnJumpName = "JumpButton"; //跳跃键在Canvas中的序号
[SerializeField] string m_btnAttackName = "AttackButton"; //攻击键在Canvas中的序号
[SerializeField] string m_btnThrowName = "E_Button"; //投掷键(额外功能键)在Canvas中的序号
[SerializeField] bool m_disableInputPadOnPC = false; //在PC上运行时是否隐藏MyInput的虚拟按键
//--虚拟摇杆用
static Vector2 axisVector;
//--任何虚拟摇杆中的按键按下了:
static bool isAnyVirtualAxisDown;
static bool isJumpButtonDown;
static bool isThrowButtonDown;
static bool isAttackButtonDown;
static MyInput g_instance;
public enum AxisOption
{
// Options for which axes to use
Both, // Use both
OnlyHorizontal, // Only horizontal
OnlyVertical // Only vertical
}
public AxisOption axesToUse = AxisOption.Both; // The options for the axes that the still will use
RectTransform moveRangeParent;
int MoveRadiusRange = 100; //The radius of movement range.
Vector2 m_StartAnchoredPos;
Vector2 m_StartDragPos;
bool m_UseX = true; // Toggle for using the x axis
bool m_UseY = true; // Toggle for using the Y axis
RectTransform m_rectTransform;
#endregion
void Awake()
{
//将EventSystem的部分放到Start时点进行检查:
StartCoroutine(GameObjFunc.IDelayDoSth(() =>
{
if (EventSystem.current == null)
{
Debug.LogWarning("NO EventSystem was found in current scene. I will create one that will be destroyed after playing.");
this.gameObject.AddComponent<EventSystem>();
}
}));
g_instance = this;
m_rectTransform = GetComponent<RectTransform>();
m_StartAnchoredPos = m_rectTransform.anchoredPosition;
moveRangeParent = m_rectTransform.parent.GetComponent<RectTransform>();
//计算可移动半径范围:
//--内圆Radius:
float stickRadius = m_rectTransform.rect.width * 0.5F;
//--外圆Radius:
float moveRadius = moveRangeParent.rect.width * 0.5F;
//--可移动范围
MoveRadiusRange = (int)(moveRadius - stickRadius);
Transform canvasTrans = GetComponentInParent<Canvas>().transform;
//如果无需显示,则在非移动的情况下关闭
if (m_disableInputPadOnPC && Application.isMobilePlatform == false)
{
canvasTrans.gameObject.SetActive(false);
return;
}
//获得按钮
Button btn = canvasTrans.GetChildByName<Button>(m_btnJumpName);
if (btn)
{
//注册跳JumpButton:
btn.onClick.AddListener(() =>
{
isJumpButtonDown = true;
});
}
btn = canvasTrans.GetChildByName<Button>(m_btnThrowName);
if (btn)
{
//注册投掷互动ButtonE
btn.onClick.AddListener(() =>
{
isThrowButtonDown = true;
});
}
btn = canvasTrans.GetChildByName<Button>(m_btnAttackName);
if (btn)
{
//注册攻击按钮Attack
btn.onClick.AddListener(() =>
{
isAttackButtonDown = true;
});
}
}
void LateUpdate()
{
if (m_clearKeysAfterFrame)
{
ClearKeysFlag();
}
}
void OnDisable()
{
//释放方向键
this.OnPointerUp(null);
}
/// <summary>
/// 传输更新虚拟轴数据到输入管理中
/// </summary>
void UpdateVirtualAxes(Vector2 value)
{
axisVector = m_StartAnchoredPos - value;
//Debug.Log("delta:" + delta);
axisVector.y = -axisVector.y;
axisVector /= MoveRadiusRange;
if (m_UseX)
{
axisVector.x = -axisVector.x;
}
}
//继承函数:Drag时触发
public void OnDrag(PointerEventData data)
{
//标记有移动;
isAnyVirtualAxisDown = true;
//新计算方法:
//获得移动差值
Vector2 posDelta = data.position - m_StartDragPos;
//如果不是双向可移动,去掉特定轴
if (!m_UseX) posDelta.x = 0;
if (!m_UseY) posDelta.y = 0;
//差值限制,利用等比三角形:差值过大时,外直角边与目标直角边成比例;
float r1 = MoveRadiusRange;
if (Vector2.SqrMagnitude(posDelta) > r1 * r1)
{
//--首先去掉0值、近似0情况:
float absX = Mathf.Abs(posDelta.x);
float absY = Mathf.Abs(posDelta.y);
if (absX < 0.01F)
{
posDelta.x = 0;
posDelta.y = r1 * (posDelta.y > 0 ? 1 : -1);
}
else if (absY < 0.01F)
{
posDelta.x = r1 * (posDelta.x > 0 ? 1 : -1);
posDelta.y = 0;
}
else
{
//三角形趋于X边比值较重(超出r的情况
float rPos = posDelta.magnitude;
//--使用等比三角的公式:x?/xPos=r1/rPos
posDelta.x = r1 / rPos * posDelta.x;
posDelta.y = r1 / rPos * posDelta.y;
}
}
Vector2 newPos = m_StartAnchoredPos + posDelta;
//否则予以移动:
//--更新移动视图
m_rectTransform.anchoredPosition = newPos;
//更新轴数据:
UpdateVirtualAxes(m_rectTransform.anchoredPosition);
}
public void OnPointerUp(PointerEventData data)
{
//标记移动虚拟轴结束:
isAnyVirtualAxisDown = false;
m_rectTransform.anchoredPosition = m_StartAnchoredPos;
UpdateVirtualAxes(m_StartAnchoredPos);
}
public void OnPointerDown(PointerEventData data)
{
isAnyVirtualAxisDown = true;
//开始拖拽时记录鼠标位置
m_StartDragPos = data.position;
}
}
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
C#
1
https://gitee.com/dragengt/UnityGlobalFuncs.git
git@gitee.com:dragengt/UnityGlobalFuncs.git
dragengt
UnityGlobalFuncs
UnityGlobalFuncs
master

搜索帮助