You need to enable JavaScript to run this app. Unity C#入门:单脚本实现多球体碰撞交互的方案咨询
优惠活动
大模型
产品
解决方案
定价
更多

Unity C#入门:单脚本实现多球体碰撞交互的方案咨询

问题背景

我是C#和Unity入门新手,仅学习3周。为练习开发能力我为自己设置了实操任务并尝试独立解决:第一个任务是模拟单个球体落地效果,已顺利完成;第二个任务是模拟多球体落地及球体间的互相碰撞效果,此时我发现现有知识储备不足以完成该需求:单个球体时逻辑完全正常,但存在多个"Player"对象时就出现了问题。

问题描述

我为每个球体都挂载了同一个脚本,但每个球体实例都处于独立的运行环境中,无法感知其他球体的存在。我尝试使用静态变量存储所有球体数据,仅部分解决了问题:运行时只有部分球体可以触发互相碰撞,无法实现全部球体的碰撞交互。
我需要了解正确的多对象交互组织逻辑,即如何正确获取并处理所有球体的相关数据,实现完整的碰撞效果。

我已将实现球体间碰撞的相关代码做了高亮标注:

// +++++++++++++++++++++++++
// +++++++++++++++++++++++++
   some code
// +++++++++++++++++++++++++
// +++++++++++++++++++++++++
完整实现代码
using System;
using UnityEngine;


public class Movement : MonoBehaviour
{
    public Transform player;
    public Transform ground;

    public float mass;    

    // 其他作用力和方向参数
    private float force = 3f;
    private float directionForceRad = 45 * (float)Math.PI / 180;
    private Vector2 acceleration;
    private Vector2 movementSpeed;
    private Vector2 delta;
    private Vector2 normal;

    // 地面参数
    private float leftEdge;
    private float rightEdge;
    private float groundAngle;
    private float cosGroundAngle;
    private float sinGroundAngle;


    private Boolean IsGrounded()
    {
        bool isGrounded = false;
        float dX = cosGroundAngle * (ground.localScale.x / 2);
        float dY = sinGroundAngle * (ground.localScale.x / 2);
        Vector2 distance = new Vector2(dX, dY) + (Vector2)ground.position - (Vector2)player.position;
        Vector2 projectionDistance = Vector2.Dot(distance, normal) * normal;

        if (projectionDistance.magnitude - 0.1 <= player.localScale.y / 2)
        {
            isGrounded = true;
        }
        return isGrounded;
    }

   
    // +++++++++++++++++++++++++
    // +++++++++++++++++++++++++
    public class Ball
    {
        public string name;
        public Vector2 movement;
        public float mass;
        public float radius;
        public Vector2 position;

        public Ball(GameObject obj, Vector2 mov, float weight)
        {
            name     = obj.name;
            radius   = obj.transform.localScale.x / 2;
            position = obj.transform.position;
            movement = mov;
            mass     = weight;
        }

    }

    static Ball[] allBalls;

    static GameObject[] balloons;

    private void CollisionOfBalloons()
    {
        Vector2 first, second;
        for (int i = 0; i < allBalls.Length; i++)
        {            
            for (int j = i; j < allBalls.Length; j++)
            {
                if (i != j)
                {
                    if (Vector2.Distance(allBalls[i].position, allBalls[j].position) <= allBalls[i].radius + allBalls[j].radius)
                    {                                             
                        first = (allBalls[j].mass * allBalls[j].movement) / allBalls[i].mass;
                        second = (allBalls[i].mass * allBalls[i].movement) / allBalls[j].mass;
                        allBalls[i].movement = first;
                        allBalls[j].movement = second;                        
                        Debug.Log("allBalls[i] = " + allBalls[i]);
                        Debug.Log("allBalls[j] = " + allBalls[j]);                        
                    }
                }
            }           
        }
    }

    // +++++++++++++++++++++++++
    // +++++++++++++++++++++++++



    void Start()
    {
        Vector2 gravity = new Vector2(0, -10);

        groundAngle    = ground.transform.rotation.eulerAngles.z * (float)Math.PI / 180;
        cosGroundAngle = (float)Math.Cos(groundAngle);
        sinGroundAngle = (float)Math.Sin(groundAngle);
        leftEdge       = ground.position.x - (ground.localScale.x * cosGroundAngle) / 2;
        rightEdge      = ground.position.x + (ground.localScale.x * cosGroundAngle) / 2;
        normal         = new Vector2(1 * sinGroundAngle, -1 * cosGroundAngle);

        // 启动前组件参数初始化
        acceleration = new Vector2(
            (force / mass) * (float)Math.Cos(directionForceRad), 
            (force / mass) * (float)Math.Sin(directionForceRad) + gravity.y
            );


        // +++++++++++++++++++++++++
        // +++++++++++++++++++++++++


        balloons = GameObject.FindGameObjectsWithTag("Player");
        allBalls = new Ball[balloons.Length];
        foreach (var item in balloons)
        {
            int ind = Array.IndexOf(balloons, item);
            allBalls[ind] = new Ball(balloons[ind], acceleration, mass);
        }

        // +++++++++++++++++++++++++
        // +++++++++++++++++++++++++
    }


    void FixedUpdate()
    {
        foreach (var item in allBalls)
        {
            if (item.name == player.name)            
                movementSpeed = item.movement;            
        }

        // 计算速度和位移
        movementSpeed   += acceleration * Time.deltaTime;
        delta           = movementSpeed * Time.deltaTime;        
        player.position = (Vector2)player.position + delta;


        // +++++++++++++++++++++++++
        // +++++++++++++++++++++++++

        foreach (var item in allBalls)
        {
            if (item.name == player.name)
            {
                item.position = player.position;
                item.movement = movementSpeed;
            }
                                      
        }
      

        CollisionOfBalloons();

        // +++++++++++++++++++++++++
        // +++++++++++++++++++++++++
                 

        // 检测碰撞并改变方向
        if ((player.position.x > (leftEdge - player.localScale.x / 2)) && 
            (player.position.x < (rightEdge + player.localScale.x / 2)) &&
            IsGrounded())
        {
            foreach (var item in allBalls)
            {
                if (item.name == player.name)
                {
                    item.movement -= 2 * (Vector2.Dot(movementSpeed, normal) * normal);
                }
            }            
        }
    }
}

内容的提问来源于stack exchange,提问作者Максим Можейко

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.21 12:45:04