Unity微信小游戏小窗口模式点击适配

1. 问题描述

项目使用UGUI方案,以点击交互为主。

微信unity方案本身只能调PixelRatio,不能直接调整Unity的分辨率,(还没有测试过"自适应屏幕尺寸"会怎么样),不过看前段时间热门的unity小游戏项目《无尽冬日》也没有对分辨率进行适配,采用了分辨率拉伸的模式。

简单以我自己的手机举例,如果正常打开微信,再打开小游戏,分辨率是1080x2461,如果把小游戏的窗口单独拖到小窗口模式,WeChatWASM.WX.OnWindowResize()的回调给的分辨率是1080x1729,但因为不能调整Unity的分辨率,所以整个画面是拉伸的。反过来,如果先打开微信,把微信拉成小窗口,再打开小游戏,之后再把小游戏全屏,效果会反过来。

画面拉伸问题不算太大,但点击响应的问题比较严重,经过测试,以从左到右为x轴,从下到上为y轴,全屏启动小游戏再拉到小窗口模式后(1080x1729),左上角的输入坐标还是正确的(0,2461), 但左下角的坐标就是错误的(0,732)(2461-1729),导致的现象是越靠近上方的按钮越有可能点对,靠近下方的就点不到了。正确的坐标和输入坐标的关系是

csharp 复制代码
Vector2 GetMousePosition()
{
    var pos = Input.mousePosition;

    int originalHeight = 2461; // 初始化时存储
    int modifiedHeight = 1729; // OnWindowResize() 回调获取
    if (originalHeight == modifiedHeight)
    {
        return pos;
    }

    float resolutionScale = 1; // 分辨率缩放
    float y = pos.y;
    pos.y = (y + (modifiedHeight - originalHeight) * resolutionScale) / modifedHeight * originalHeight;
    return pos;
}

项目用的是旧输入系统,一开始尝试了继承StandaloneInputMoudle进行覆盖,但好像不起作用(也可能是没改对?),最后解决方法是换用了InputSystem,新的输入系统还是比较好用的。

2. 从UnityEngine.Input升级到UnityEngine.InputSystem

  1. 首先要更新UGUI源码(如果使用embbed模式), 虽然版本号一直是1.0.0, 但还是有多次修改的
  2. Window > PackageManager 安装 Input System (本文使用的是1.7.0版本)
  3. Editor > Project Settings > OtherSettings > Active Input Handling, 改为"Input System Package" (关闭旧的输入系统)
  4. UGUI的事件接入: 找到场景中的EventSystem, 把原本的StandaloneUIInputModule删掉, 挂一个InputSystemUIInputModule上去

3. 常用API的直接近似替换

需要注意判空

鼠标:

  • Input.mousePosition -> Mouse.current.position.ReadValue()
  • Input.GetMouseButton(index) -> Mouse.current.leftButton.isPressed | Mouse.current.rightButton.isPressed (下面省略)
  • Input.GetMouseButtonDown(index) -> Mouse.current.leftButton.wasPressedThisFrame
  • Input.GetMouseButtonUp(index) -> Mouse.current.leftButton.wasReleasedThisFrame
  • Input.GetAxis("Mouse ScrollWheel") -> Mouse.current.scroll.ReadValue().y / 120f

键盘(实际只有编辑器在用):

  • Input.GetKey(KeyCode.W) -> Keyboard.current.wKey.isPressed
  • Input.GetKey(keyCode) -> switch case
  • 键盘的Down\Up也是wasPressedThisFrame\wasReleasedThisFrame

另外鼠标的逻辑替换需要注意判断触屏,以Input.mousePosition为例

csharp 复制代码
public static class Input
{
    public static Vector2 mousePosition
    {
        get {
#if !UNITY_EDITOR && UNITY_WEBGL
            var pos = TouchScreen.current?.primaryTouch.position.ReadValue() ?? Vector2.zero;
#else
            var pos = Mouse.current?.position.ReadValue() ?? Vector2.zero;
#endif
            return pos;
        }
    }
}

4. 添加作用到UGUI的坐标转换

为了方便修改,直接把InputSystem包改成embbed模式(包文件夹从Library/PackageCache移动到Packages文件夹)

新建Packages/com.unity.inputsystem@xxx/InputSystem/Controls/Processors/ResolutionVector2Processor.cs

csharp 复制代码
namespace UnityEngine.InputSystem.Processors
{
    public class ResolutionVector2Processor : InputProcessor<Vector2>
    {
        // 这些参数自行找时机传递过来即可
        private static int s_OriginalHeight = 0;
        private static int s_ModifiedHeight = 0;
        private static float s_ResolutionScale = 1.0f;

        public override Vector2 Process(Vector2 value, InputControl control)
        {
            // 和第一节的逻辑相同
            if (s_OriginalHeight == s_ModifiedHeight) return value;

            float y = value.y;
            value.y = (y + (s_ModifiedHeight - s_OriginalHeight) * s_ResolutionScale) / s_ModifiedHeight * s_OriginalHeight;
            return value;
        }

        public override string ToString()
        {
            return $"ResolutionVector2()";
        }
    }
}

Packages/com.unity.inputsystem@xxx/InputSystem/InputManager.cs里面注册一下

csharp 复制代码
internal void InitializeData()
{
    // ...
    processors.AddTypeRegistration("ResolutionVector2", typeof());
    // ...
}

然后在unity中Project窗口选中Packages/com.unity.inputsystem@xxx/InputSystem/Plugins/PlayerInput/DefaultInputActions.inputactions

点击Inspector窗口的Edit asset

ActionMaps选择UI

Actions选择 Point > touch*/position [Touchscreen]

在Processors中添加刚才新建的ResolutionVector2,保存即可

5. Input.mousePosition的替换

回到第3节的代码,把转换逻辑加进去即可

相关推荐
咸鱼永不翻身3 小时前
Lua脚本事件检查工具
unity·lua·工具
leo__5204 小时前
单载波中继系统资源分配算法MATLAB仿真程序
算法·matlab·unity
努力长头发的程序猿6 小时前
Unity使用ScriptableObject序列化资源
unity·游戏引擎
mxwin6 小时前
Unity Shader 手写基于 PBR 的 URP Lit Shader 核心光照计算
unity·游戏引擎·shader
小贺儿开发6 小时前
Unity3D 智能云端数字标牌系统
unity·阿里云·人机交互·视频·oss·广告·互动
魔士于安6 小时前
Unity windows 同步 异步 打开文件文件夹工具
游戏·unity·游戏引擎·贴图·模型
魔士于安7 小时前
unity lowpoly 风格 城市 建筑 道路 交通标志
游戏·unity·游戏引擎·贴图·模型
mxwin7 小时前
Unity GPU Shader 性能优化指南
unity·游戏引擎·shader
董董女友19 小时前
unity mcp 配置指南
unity·游戏引擎
垂葛酒肝汤1 天前
Unity的可视化网格和文字标签
unity·游戏引擎