如何让Unity WebGL游戏适配浏览器窗口?点击偏移问题求解
解决Unity WebGL缩放后交互错位的问题
这问题我之前帮朋友踩过坑——用CSS transform: scale()做视觉缩放确实会导致Unity交互错位,核心原因是Unity的输入系统是基于原始画布尺寸计算的,和你用CSS做的视觉缩放完全脱节,相当于画面被拉伸了,但碰撞检测、UI点击的坐标还是按原始1152×648来算的,自然点不准。
给你几个靠谱的解决方案,按优先级排序:
1. 用Unity内置的WebGL自适应缩放(最推荐,零额外代码)
Unity本身就提供了WebGL画布的自适应功能,完全不用自己写JS,还能保证输入和视觉同步:
- 打开Unity编辑器,进入
Edit > Project Settings > Player,切换到WebGL平台 - 在
Resolution and Presentation面板里:- 保持
Default Canvas Width=1152,Default Canvas Height=648(满足大屏用户的高分辨率需求) - 勾选
Resize Canvas,然后把Render Mode改成Scale to Fit(这个模式会保持游戏的原始宽高比,自动缩放适配窗口,不会拉伸变形;如果需要填充整个窗口可以选Scale to Fill,但会裁剪边缘) - 保持默认的
WebGL Template即可,Unity会自动生成适配的JS代码,输入坐标会自动对应缩放后的视觉位置
- 保持
用这个方案,大屏用户看到的是原始高分辨率,小屏用户会自动缩放适配,而且完全不会有交互错位的问题。
2. 手动修正Unity输入坐标(自定义JS场景下可用)
如果必须保留你自己写的JS缩放逻辑,那需要在Unity里修正输入坐标,让它和CSS缩放比例同步:
第一步:在JS里存储缩放比例
修改你的resizeGame函数,把当前的缩放比例存到全局变量:
function resizeGame() { var winSize = {w:1152, h:648}; var fill1Div = document.getElementById('gameContainer'); var width = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth; var height = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight; var scaleWidth = width / winSize.w; var scaleHeight = height / winSize.h; var bgScale = scaleWidth < scaleHeight ? scaleWidth : scaleHeight; bgScale = bgScale >= 1 ? 1 : bgScale; // 存储缩放比例到全局变量 window.gameScale = bgScale; var bgTransformScale = "scale(" + bgScale + ")"; fill1Div.style.transform = bgTransformScale; fill1Div.style.webkitTransform = bgTransformScale; fill1Div.style.MozTransform = bgTransformScale; fill1Div.style.msTransform = bgTransformScale; fill1Div.style.OTransform = bgTransformScale; } window.addEventListener("resize", resizeGame); window.addEventListener("orientationchange", resizeGame); resizeGame(); // 给Unity提供获取缩放比例的方法 function GetGameScale() { return window.gameScale || 1; }
第二步:在Unity C#脚本里修正输入坐标
写一个脚本,从JS获取缩放比例,然后修正鼠标/触摸坐标:
using UnityEngine; public class InputScaler : MonoBehaviour { private float _scaleFactor = 1f; void Start() { // 初始化时获取缩放比例 _scaleFactor = GetGameScale(); } void Update() { // 实时更新缩放比例(窗口变化时同步) _scaleFactor = GetGameScale(); // 修正鼠标坐标:把浏览器窗口坐标转换成游戏原始画布的坐标 Vector2 scaledMousePos = new Vector2( Input.mousePosition.x / _scaleFactor, Input.mousePosition.y / _scaleFactor ); // 之后所有交互逻辑都用scaledMousePos代替Input.mousePosition // 比如UI点击、射线检测等 ExampleRaycast(scaledMousePos); } // 调用JS全局方法获取缩放比例 [System.Runtime.InteropServices.DllImport("__Internal")] private static extern float GetGameScale(); // 示例:用修正后的坐标做射线检测 void ExampleRaycast(Vector2 mousePos) { Ray ray = Camera.main.ScreenPointToRay(mousePos); if (Physics.Raycast(ray, out RaycastHit hit)) { // 处理点击逻辑 } } }
把这个脚本挂在你的主相机或者全局管理器上,所有依赖鼠标/触摸的交互都用修正后的坐标,就能解决错位问题。
3. 用CSS zoom属性代替transform(兼容性有限)
如果你只需要兼容Chrome/Edge这类浏览器,可以把transform: scale()换成zoom属性:
// 替换原来的transform相关代码 fill1Div.style.zoom = bgScale;
zoom是浏览器对整个元素的缩放,包括输入事件的坐标,所以不会出现错位。但注意Firefox对zoom的支持很差,所以这个方案只适合特定场景。
内容的提问来源于stack exchange,提问作者zack_falcon
相关产品推荐
相关产品推荐

