Unity's practical experience

Back in the day, the game of pinching needles was considered one of the most popular small games all over the Internet. There are still many arcades that win blind boxes through similar games.
The game effect is as follows:
insert image description here

Through the above game demo, let's analyze the production ideas of this game.
1. The rotation of the disc.
2. Dynamically generate the pins that need to be inserted.
3. Movement of the needle.
4. Rotation of the needle (synchronized with the rotation of the turntable).
5. Game score.
6. Judgment of game success and failure.

rotation of the disc

First of all, let's realize the rotation of the disc, we can directly use the interface provided by Unity: transform.Rotate

public float speed = 90;
transform.Rotate(new Vector3(0, 0, speed * Time.deltaTime));

When running the game at this time, you will find that the turntable is rotating counterclockwise. Based on everyone's habit, clockwise operation will be more comfortable. We need to adjust the rotation method and add a negative number to the rotation angle of each frame. Because it is stipulated in Unity, adding a positive angle is counterclockwise, and a negative angle is clockwise.
Since our disc game needs to be rotated at the beginning, we will perform the rotation operation directly in Update

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class RotateSelf : MonoBehaviour {
    
    

    public float speed = 90;
    
    // Update is called once per frame
    void Update () {
    
    
        transform.Rotate(new Vector3(0, 0, -speed * Time.deltaTime));
    }
}

instantiated needle

First analyze, when will there be no needles below and need to be instantiated?
1. When first entering the game, the scene has only one disc, and the needle needs to be instantiated below.
2. When the player shoots the needle, the needle flies to the disc, and the lower part needs to be instantiated.
Then, when instantiating the needle, the needle needs to be displayed at the specified location.
Generally, our game needs to establish a game manager to control the progress of the game globally. Here we create a new GameManager.cs to manage our game.
Control the instantiation of pins in the Game Manager.
Ways to instantiate a needle:

public GameObject pinPrefab;
private Transform spawnPoint;-- 实例化位置

void Start () {
    
    
    spawnPoint = GameObject.Find("SpawnPoint").transform;
}

void SpawnPin()
{
    
    
    GameObject.Instantiate(pinPrefab, spawnPoint.position, pinPrefab.transform.rotation);
}

Start the game and instantiate the needle for the first time

void Start () {
    
    
    SpawnPin();
}

instantiated each time the left mouse button is pressed

private void Update()
{
    
    
    if (Input.GetMouseButtonDown(0))
    {
    
    
        SpawnPin();
    }
}

Needle moves to disc

In order to easily control the movement of each needle, we add a Pin.cs class to the needle to manage the properties and movement of the needle.
The needle has four states: whether to come to the starting point (ie isReach), whether to fly to the disc (ie isFly), in the
initial state, both of these are false, that is

private bool isFly = false;
private bool isReach = false;

When the player presses the left mouse button, the state is set to true, that is, the StartFly method of Pin is executed to
obtain Pin.cs

// GameManager.cs
void SpawnPin()
    {
    
    
        currentPin = GameObject.Instantiate(pinPrefab, spawnPoint.position, pinPrefab.transform.rotation).GetComponent<Pin>();
    }
// GameManager.cs
private void Update()
{
    
    
    if (Input.GetMouseButtonDown(0))
    {
    
    
        currentPin.StartFly();
        SpawnPin();
    }
}

// Pin.cs
public void StartFly()
{
    
    
    isFly = true;
    isReach = true;
}

The state of the needle, we detect in Update, the movement of the needle uses Vector3.MoveTowards (current position, target position, speed), when the current position is less than a certain value from the target position (here we choose 0.01), we think that we have reached the target Location

// Pin.cs
private Transform startPoint;
private Vector3 targetCirclePos;

void Start () {
    
    
    startPoint = GameObject.Find("StartPoint").transform;
}

void Update () {
    
    
    if (isFly == true)
    {
    
    
        if (isReach == false)
        {
    
    
            transform.position = Vector3.MoveTowards(transform.position, startPoint.position, speed * Time.deltaTime);
            if (Vector3.Distance(transform.position, startPoint.position) < 0.01f)
            {
    
    
                isReach = true;
            }
        }
    }
    else
    {
    
    
         transform.position = Vector3.MoveTowards(transform.position, targetCirclePos, speed * Time.deltaTime);
        if(Vector3.Distance( transform.position,targetCirclePos) < 0.01f)
        {
    
    
            transform.position = targetCirclePos;
            isFly = false;
        }
    }
}

Rotation of the needle

In order to make the needle rotate synchronously with the disc, the easiest way is to place the needle as a sub-object under the rotating body (disc) when the needle reaches the position of the disc to achieve synchronous rotation.

// Pin.cs
private Transform circle;
transform.parent = circle;

game score

Setting: Every time a needle is fired, the score +1

// GameManager.cs
public Text scoreText;
private int score = 0;

score++;
scoreText.text = score.ToString();

failure success judgment

Since the needle is a slender and straight object, in order to increase the difficulty, we add a circle to a section of the needle (that is, the other end of the insertion disc) as the head of the needle (PinHead), which is used as the detection object.
We only need to judge whether the game continues or fails based on whether there is a collision, and no collision effect is required, so we choose to use the trigger Trigger detection.
First of all, let's learn about physics.

Collision conditions

1. To collide, both parties must have colliders.
2. One side of the movement must have a rigid body, and it does not matter whether the other side has a rigid body or not.
Note: If the moving party has no rigid body, it will collide with the static rigid body, which is equivalent to not colliding with

Two ways to get in touch

1.Collision collision, causing physical collision, the OnCollision event can be executed during the collision.
2. Trigger triggers, cancels all physical collisions, and executes the OnTrigger event when triggered.
Note: It is impossible for two objects to contact to produce collision + contact at the same time, at most one. But AB can collide and AC can trigger.

Collision collision

(1) Both parties have a collision body
(2) The moving party must have a rigid body
(3) Both parties cannot check Kinematic kinematics at the same time.
(4) Neither party can check the Trigger trigger

Trigger trigger

(1) Both sides have collision bodies
(2) The moving party must be a rigid body
(3) At least one party should check the Trigger trigger
After understanding the physics knowledge above, the next step is the practical operation, don't worry, it's very simple ~
we need Add components to PinHead:
1.Collider 2D, since PinHead is a circle, we add Circle Collider 2D for him. Check Is Trigger.
2. Add Rigibody 2D component
3. Add PinHead tag (Tag)
4. Add PinHead.cs for trigger condition detection.
In the end, the PinHead looks like this:

insert image description here

//PinHead.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PinHead : MonoBehaviour {
    
    

    private void OnTriggerEnter2D(Collider2D collision)
    {
    
    
        if (collision.tag == "PinHead")
        {
    
    
            //游戏结束
        }
    }
}

Game over processing

In the game manager, manage the operation after game failure, the flag of game failure, stop spinning operation after failure, etc.

// GameManager.cs
private bool isGameOver = false;
public void GameOver()
{
    
    
    if (isGameOver) return;
    GameObject.Find("Circle").GetComponent<RotateSelf>().enabled = false;
    isGameOver = true;
}

In Update, it is necessary to add the judgment of whether the game fails

if (isGameOver) return;


Note: The reference materials of this project are from the source code link of the siki college project: https://gitee.com/shirln/StickPin

Guess you like

Origin blog.csdn.net/shirln/article/details/122557178