Unity 2D手游LineRenderer异常:球运动时触摸以(0,0)为起点
问题描述
在2D Unity移动端游戏中,触摸拖拽小球时,LineRenderer会从小球位置延伸至拖拽方向,功能正常;但当小球处于运动状态(未停止)时触摸屏幕,后续生成的LineRenderer会以(0,0)为起点,而非当前小球所在位置。
- 正常效果:

- 异常效果:

即便代码中通过!hasMoved限制小球运动时不响应触摸,但若在小球停止前触摸屏幕,后续生成的LineRenderer仍会出现起点错误的问题。
相关代码片段
void Update() { if (Input.touchCount > 0 && !hasMoved) { touch = Input.GetTouch(0); if (touch.phase == TouchPhase.Began) { dragStart(); } if (touch.phase == TouchPhase.Moved) { Dragging(); } if (touch.phase == TouchPhase.Ended) { DragRelease(); } } } void dragStart() { dragStartposition = transform.position; dragStartposition.z = 0; gostergeLine.positionCount = 1; gostergeLine.SetPosition(0,transform.position); } void Dragging() { Vector3 draggingPos = Camera.main.ScreenToWorldPoint(touch.position); draggingPos.z = 0; gostergeLine.positionCount = 2; gostergeLine.SetPosition(1, draggingPos); } void DragRelease() { gostergeLine.positionCount = 0; Vector3 dragReleasePos = Camera.main.ScreenToWorldPoint(touch.position); dragReleasePos.z = 0; Vector3 forceVec = dragStartposition - dragReleasePos; forcePower = forceVec.magnitude; if(forcePower > 45) { topRb.velocity = forceVec * 45; } else { topRb.velocity = forceVec * forcePower; } }
问题原因
小球运动时hasMoved为true,此时触摸的TouchPhase.Began不会触发dragStart()初始化LineRenderer起点;如果触摸持续到小球停止(hasMoved变为false),后续的TouchPhase.Moved会直接调用Dragging(),此时LineRenderer的position[0]从未被设置,默认使用(0,0)作为起点。同时触摸状态没有被及时重置,导致跨状态的触摸事件残留。
解决方案
- 增加运动时的LineRenderer重置逻辑
在Update开头添加判断,小球运动时直接清空LineRenderer状态,避免残留:
void Update() { // 小球运动时强制清空LineRenderer if (hasMoved && gostergeLine.positionCount > 0) { gostergeLine.positionCount = 0; } if (Input.touchCount > 0 && !hasMoved) { touch = Input.GetTouch(0); if (touch.phase == TouchPhase.Began) { dragStart(); } else if (touch.phase == TouchPhase.Moved) { Dragging(); } else if (touch.phase == TouchPhase.Ended) { DragRelease(); } } }
- Dragging时校验起点是否初始化
在Dragging()中增加判断,确保LineRenderer起点已被设置,未设置则自动初始化:
void Dragging() { // 确保起点已初始化 if (gostergeLine.positionCount == 0) { dragStart(); } Vector3 draggingPos = Camera.main.ScreenToWorldPoint(touch.position); draggingPos.z = 0; gostergeLine.positionCount = 2; gostergeLine.SetPosition(1, draggingPos); }
- 精准控制hasMoved状态切换
通过Rigidbody的速度值判断小球是否停止,避免状态切换延迟:
void FixedUpdate() { // 当小球速度趋近于0时标记为停止状态 hasMoved = topRb.velocity.magnitude >= 0.1f; }
内容的提问来源于stack exchange,提问作者Fahrettin Özkan
相关产品推荐
相关产品推荐

