Unity(C#)游戏开发需求:小球撞墙不互撞、白球置红球后方及点击计分
Hey Tommy, let's walk through each of your requirements one by one—this is all straightforward to set up in Unity with C#!
The easiest way to handle this is using Unity's Layer Collision Matrix:
- First, create two new layers: go to
Edit > Project Settings > Tags and Layers, addBallLayerandWallLayer. - Assign all your balls to the
BallLayer, and all wall objects toWallLayer. - Open the Physics settings (same menu as above, go to the Physics tab for 3D, Physics 2D for 2D games). In the Layer Collision Matrix, uncheck the box where
BallLayerintersects with itself—this stops balls from colliding with each other. Make sure the box forBallLayer↔WallLayeris checked so balls bounce off walls. - Add a
Rigidbody(3D) orRigidbody2D(2D) to each ball (enable gravity if you want them to fall, or turn it off for floating movement). Also add a collider component (likeSphereColliderorCircleCollider2D) to balls and walls. Walls can use static colliders for better performance.
Unity's physics system will handle the bouncing automatically, but if you want custom behavior (like adjusting bounce force), you can add this script to your balls:
using UnityEngine; public class BallBounce : MonoBehaviour { [SerializeField] private float bounceForce = 5f; private void OnCollisionEnter(Collision collision) // Use OnCollisionEnter2D for 2D { if (collision.gameObject.layer == LayerMask.NameToLayer("WallLayer")) { // Add custom bounce logic here if needed GetComponent<Rigidbody>().AddForce(collision.contacts[0].normal * bounceForce, ForceMode.Impulse); } } }
This is all about render ordering:
For 2D Games:
- Use Sorting Layers: Go to
Edit > Project Settings > Tags and Layers, create two new Sorting Layers:RedBallRenderandWhiteBallRender. DragWhiteBallRenderbelowRedBallRenderin the list (lower layers render behind higher ones). - Select all red balls, go to their
SpriteRenderercomponent, set the Sorting Layer toRedBallRender. Do the same for white balls, selectingWhiteBallRender. Alternatively, you can just adjust the Order in Layer field—set red balls to1and white balls to0(higher numbers render on top).
For 3D Games:
- Adjust the Z-axis position of your balls. If your camera is facing along the Z-axis (common for top-down or side views), set white balls' Z value to be higher than red balls' (e.g., red balls at Z=0, white at Z=1)—this will make whites render behind reds.
We can use either OnMouseDown() (simple) or IPointerClickHandler (more flexible for UI integration). Here's a complete script that works for both 2D and 3D:
First, add tags to your balls: create WhiteBall and RedBall tags, then assign them to the respective balls. Then attach this script to every ball (or create a manager script to handle clicks globally—this is simpler for starters):
using UnityEngine; using UnityEngine.UI; public class BallScoreHandler : MonoBehaviour { [SerializeField] private Text scoreDisplay; private int currentScore = 0; // Works for both 2D and 3D if colliders are set up private void OnMouseDown() { if (gameObject.CompareTag("WhiteBall")) { currentScore++; Debug.Log($"Score increased! Current: {currentScore}"); } else if (gameObject.CompareTag("RedBall")) { currentScore--; Debug.Log($"Score decreased! Current: {currentScore}"); } UpdateScoreUI(); } private void UpdateScoreUI() { if (scoreDisplay != null) { scoreDisplay.text = $"Score: {currentScore}"; } } }
- Don't forget to drag your UI Text element into the
scoreDisplayfield in the Inspector for each ball, or makecurrentScorestatic if you want a single manager script to handle all clicks.
If you prefer using IPointerClickHandler (better if you have UI elements overlapping), add an EventSystem to your scene (right-click in Hierarchy > UI > Event System), and add a PhysicsRaycaster (3D) or Physics2DRaycaster (2D) component to your main camera. Then modify the script to implement the interface:
using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.UI; public class BallScoreHandler : MonoBehaviour, IPointerClickHandler { [SerializeField] private Text scoreDisplay; private static int currentScore = 0; // Static so all balls share the same score public void OnPointerClick(PointerEventData eventData) { if (gameObject.CompareTag("WhiteBall")) { currentScore++; } else if (gameObject.CompareTag("RedBall")) { currentScore--; } UpdateScoreUI(); } private void UpdateScoreUI() { scoreDisplay?.text = $"Score: {currentScore}"; } }
That's all! Each part works independently, so you can test them one by one to make sure everything behaves as expected.
内容的提问来源于stack exchange,提问作者Tommy_Gun

