想从头开始做一款独游,从嘴基本的触控杆做起,真是一波三折

方案准备

这次的客户端打算用Jengine框架来做,热更新基于ilruntime

  1. 一开始参考了林新发的方案
public class JointedArm : ScrollRect, IPointerDownHandler
{}

继承自ScrollRect的对象设置了center后可以很自然地成为一个摇杆,但是因为采用了ilruntime热更新方案,而这又属于跨域继承(想尽可能地把代码放在热更工程)
写了类在主工程继承了上面的父类和接口,利用框架里提供的工具生成了适配器,但是实际上使用起来出现了继承的接口没有产生回调,继承自ScrollRect重写的方法有回调,但是center物体没有发生移动,所以回调的数值一直是初始值不变,尝试去掉热更脚本的classbind,手动挂上ScrollRect是有正常的摇杆的表现的,在ilruntime下还是尽量避免跨域继承,所以放弃这个方案

2.计算触摸点与center的距离,手动控制物体偏移

//通过运算并normalized后求出两点之间的方向
                Vector3 vector = Input.mousePosition - beginPos;
                vector = vector.normalized;

                //这里先是求出两点之间的距离 并且同mathf.Clamp进行一个范围的限制,然后在把这个距离与vector 两点之间的方向相乘 得出点点所在的位置
                rocker.transform.localPosition =
                    Mathf.Clamp(Vector3.Distance(beginPos, Input.mousePosition), 0, 80f) * vector;

一个摇杆运行很正常,但是放上第二个摇杆的时候出现了两个摇杆一起动的情况,需要约束下点击操作的摇杆
3. 摇杆区域识别

if (Input.GetMouseButtonDown(0) && RectTransformUtility.RectangleContainsScreenPoint(_touchArea, Input.mousePosition, UiCamera)){}

然后就遇见了非常坑的地方, 调用完RectTransformUtility.RectangleContainsScreenPoint后调用Input.mousePosition去获取点击坐标得到的值是(0,0),但是在执行过几条程序之后,例如打印,Input.mousePosition就能得到正确的值,这非常地不可靠,所以要换个判断点击区域的方案
4. 摇杆识别进阶
手写一个方案来识别点击是否在指定区域

private bool IsTouchArea(RectTransform area, Vector2 position)
        {
            var rectSize = area.parent.parent.GetComponent<RectTransform>().rect.size;
            var localPosition = area.localPosition;
            Debug.Log($"{name} positon{position} localPosition:{localPosition} ");
            var areaLocalPosition = localPosition;
            var touchX = position.x - Screen.width / 2;
            var touchY = position.y - Screen.height / 2;
            if (touchX > areaLocalPosition.x - area.rect.width/2 && touchX < areaLocalPosition.x + area.rect.width/2)
            {
                if (touchY > areaLocalPosition.y - area.rect.height/2 && touchY < areaLocalPosition.y + area.rect.height/2)
                {
                    return true;
                }
            }
            return false;
        }

这种方法看似没有问题,但是我的Canvas是有设置Canvas Scaler的,当屏幕尺寸与设置的Canvas Scaler不同时区域判断就会不准,所以要加入缩放参数
···
var areaLocalPosition = localPosition;
var scale = rectSize.x/Screen.width;
var touchX = position.x - Screen.width / 2;
var touchY = position.y - Screen.height / 2;
touchX = touchX * scale;
touchY = touchY * scale;
···

打赏
支付宝 微信
上一篇 下一篇