C#全屏网格Chunk拖拽系统世界坐标异常问题求助
全屏Chunk网格拖拽系统异常修复方案
问题背景
基于C#实现全屏16x16尺寸的Chunk网格系统,支持鼠标拖拽平移:当拖拽偏移超过16单位时重置偏移,并将超出屏幕的Chunk重定位到对侧。目前在var worldPosition = new long2(nx + totalOffset.x, ny + totalOffset.y);行存在两处异常:
- 同Y轴的Chunk世界坐标Y值混乱(如从-32变为-48再到-64)
- 拖拽到左上区域正常,但右下区域无反应
异常1:同Y轴Chunk世界坐标Y值错乱
根源分析
ToInt方法负数计算逻辑错误:处理负数偏移时,Mathf.CeilToInt(f.y / r) * (int)r的计算逻辑会导致偏移量计算偏差。例如f.y=-17、r=16时,计算结果为-16,但实际应该是-32(偏移超过16单位,需向下取整到下一个Chunk边界)。- 世界坐标计算未绑定Chunk网格位置:当前用屏幕重定位后的
nx/ny加totalOffset计算世界坐标,未结合Chunk在原始网格中的行列位置,导致同Y轴Chunk因屏幕位置不同,世界坐标出现差异。
修复代码
- 修正
ToInt方法,统一用FloorToInt保证正负偏移计算一致:
public static Vector2Int ToInt(this Vector2 f, float r) { var x = Mathf.FloorToInt(f.x / r) * (int)r; var y = Mathf.FloorToInt(f.y / r) * (int)r; return new Vector2Int(x, y); }
- 基于Chunk原始网格行列计算世界坐标,替代原屏幕位置的计算方式:
// 替换原worldPosition计算行 var worldX = (x * ChunkSize) + totalOffset.x; var worldY = (y * ChunkSize) + totalOffset.y; var worldPosition = new long2(worldX, worldY);
异常2:拖拽右下区域无反应
根源分析
- 偏移重置触发条件过严:
Mathf.Abs(co.x) > ChunkSize的判断,当偏移刚好等于16时不会触发重置,导致右下方向拖拽时无法触发Chunk重定位。 - 取模运算负数处理错误:
@new.x % screenWidth在@new.x为负数时结果为负,导致nx超出屏幕范围,uiRect.Contains判断错误,Chunk无法正确重定位到右下区域。 - 拖拽偏移更新逻辑冗余:
HandleDragEvent中CurrentOffset += position - lastPosition的冗余计算可能引入精度问题,且未做边界约束。
修复代码
- 调整偏移重置触发条件为大于等于ChunkSize:
var bx = Mathf.Abs(co.x) >= ChunkSize; var by = Mathf.Abs(co.y) >= ChunkSize;
- 修正取模运算,确保结果为正:
// 替换原nx、ny计算行 var nx = (@new.x % screenWidth + screenWidth) % screenWidth; var ny = (@new.y % screenHeight + screenHeight) % screenHeight;
- 简化拖拽偏移更新逻辑,避免冗余计算:
private bool HandleDragEvent(bool changed) { if (Event.current.type == EventType.MouseDrag && (Event.current.button == 0 && Event.current.modifiers == EventModifiers.Alt || Event.current.button == 2)) { var delta = Event.current.delta; CurrentOffset -= delta * dragForce; _zoomCoordsOrigin = CurrentOffset; changed = delta != Vector2.zero; Event.current.Use(); } return changed; }
额外优化
- 确保
totalOffset累计正确:在偏移重置时,将计算出的offset累加到totalOffset中,保证世界坐标的全局偏移累计准确:
if (resetDelta) { var x = co.x; var y = co.y; if (bx) x = 0; if (by) y = 0; ui.CurrentOffset = new Vector2(x, y); totalOffset += offset; // 新增:累计全局偏移 }
内容的提问来源于stack exchange,提问作者z3nth10n
相关产品推荐
相关产品推荐

