You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity+Photon 2D多人游戏如何避免玩家间碰撞?

Unity+Photon 2D多人游戏:禁用玩家间碰撞解决方案

问题描述

我正在使用Unity和Photon开发一款2D多人游戏,目前遇到玩家互相碰撞的问题,希望禁用该行为。我使用了Unity InputSystem,以下是玩家预制体设置及PlayerController脚本片段:

玩家预制体碰撞设置:
玩家预制体碰撞设置

PlayerController脚本片段:

void OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info){
        if(stream.isWriting){
            stream.SendNext(transform.position);
            stream.SendNext(localPlayerName.text);
        } else{
            targetPosition = (Vector3)stream.ReceiveNext();
            remotePlayerName.SetText((string)stream.ReceiveNext());
        }
    }

private void FixedUpdate()
    {
        if(PhotonView.isMine){
            if(movementInput != Vector2.zero){
                int count = gameObject.GetComponent<Rigidbody2D>().Cast(
                    movementInput,
                    movementFilter,
                    castCollisions,
                    moveSpeed * Time.fixedDeltaTime + collisionOffset
                );

                if(count == 0){
                    transform.position += (Vector3)movementInput * moveSpeed * Time.fixedDeltaTime;                
                }
            }
        } else {
            moveOtherPlayer();
        }
    }

private void moveOtherPlayer() {
        transform.position = Vector3.Lerp(transform.position, targetPosition, 0.25f);
    }

void OnMove(InputValue movementValue){
        this.movementInput = movementValue.Get<Vector2>();
    }

解决方案

下面是几种直接有效的实现方式:

方法1:利用Unity碰撞层(最推荐)

  • 在Unity编辑器的Layers面板新建Player层,将所有玩家预制体的Layer设为该层
  • 打开Edit > Project Settings > Physics 2D,找到Layer Collision Matrix
  • 取消Player层与自身的碰撞勾选(矩阵中Player行和列的交叉点)
  • 注意:如果代码里的movementFilter是ContactFilter2D,确保它没有额外冲突的过滤规则

方法2:修改ContactFilter2D适配现有代码

你的移动逻辑用到了Rigidbody2D.Cast和movementFilter,可以直接在过滤器中排除玩家层:
在PlayerController的Start()方法中添加:

void Start()
{
    int playerLayer = LayerMask.NameToLayer("Player");
    // 排除Player层的碰撞检测
    movementFilter.SetLayerMask(~(1 << playerLayer));
    movementFilter.useLayerMask = true;
}

这样本地玩家的移动检测就不会识别其他玩家,自然不会触发碰撞阻挡

方法3:动态忽略玩家间碰撞

在玩家预制体的Awake()方法中添加逻辑,让所有玩家实例互相忽略碰撞:

void Awake()
{
    Collider2D selfCollider = GetComponent<Collider2D>();
    foreach (GameObject player in GameObject.FindGameObjectsWithTag("Player"))
    {
        if (player != gameObject)
        {
            Collider2D otherCollider = player.GetComponent<Collider2D>();
            if (otherCollider != null)
            {
                Physics2D.IgnoreCollision(selfCollider, otherCollider);
            }
        }
    }
}
  • 记得给玩家预制体添加统一的Player标签
  • 新生成的玩家会自动忽略已有玩家的碰撞,适合动态生成场景

额外优化提示

  • 远程玩家用Vector3.Lerp移动时,建议把远程玩家的Rigidbody2D设为Kinematic(运动学),不需要物理模拟,避免碰撞抖动
  • 本地玩家的Rigidbody2D属性设置要匹配移动逻辑,减少意外物理交互

内容的提问来源于stack exchange,提问作者Ahmed Zrouqui

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 17:39:53