Unity3d development tutorial: Angry Birds

Time:2021-11-24

1、 Foreword

“Angry birds” was released in December 2009. Due to its highly addictive game, it soon became the most successful mobile game ever.

In this tutorial, we will implement a replica of “angry birds” in “unity”. The most complex part of the game is the physical system, but thanks to unity, we don’t have to worry too much.

As usual, everything will be explained as simply as possible so that everyone can understand it.

The following are the of the projectpreview

在这里插入图片描述

2、 Source code

UI resources:
http://xiazai.jb51.net/202106/yuanma/picturezy_jb51.rar

Source code:
http://xiazai.jb51.net/202106/yuanma/Game_AngryBirds_jb51.rar

3、 Text item version

Unity5.0.0f4

1. Set camera

Click main cameras and clickHierarchy panelSet the background color to a friendly blue tone (red = 187, green = 238, blue = 255) and adjust the size. The position is shown in the following figure:

在这里插入图片描述

2. Ground setting

Ground map settings
In order to prevent copyright problems, we cannot use the original “angry birds” graphics in this tutorial. Instead, we will draw our own sprite to make them look like the original game.

Let’s start with the drawing tool of our choice:

在这里插入图片描述

After saving it into our project, we can see in the project area:

在这里插入图片描述

Then inInspectorModify import settings:

在这里插入图片描述

Note: pixels per unit pixel goes to unit value 16, which means that 16×16 pixels will fit a unit in the game world. We will use this value for all our textures. We chose 16 because the size of the bird will have a 16×16 pixel after we want it to have a unit size in the game world.

OK, now we can drag the picture from the project area into the scene:

在这里插入图片描述

Let’s seeInspectorLocate the ground at (0, – 2), so it is not a part of the ground if it is not y = 0:

在这里插入图片描述

Ground object setting
Now the ground is just an image, that’s all. It is not a part of the physical world. Things will not collide with it or stand on it. We need to add a collider to make it a part of the physical world, which means that things will be able to stand on its top rather than fall into its middle.

Add boxcollider2d component:

在这里插入图片描述

3. Boundary setting

Create an empty object named borders

在这里插入图片描述

Zero position:

在这里插入图片描述

Now, we will add some invisible areas to the left, right and top of our level. Whenever something enters that area, it should be destroyed. This kind of behavior can be through trigger, which is almost just a trigger. It receives collision information, but it will not conflict with anything.

Add Collider:

在这里插入图片描述

Tick

Is Trigger

After that, we can add two more triggers to the right and top of the level:

在这里插入图片描述

If we look at the scene, then we can see how the trigger is well aligned with our background:

在这里插入图片描述

Now we still have to ensure that anything entering the border will be destroyed immediately. Such behavior can be through the script borders:

Create script borders.cs:

在这里插入图片描述

Add it to the boundary object:

在这里插入图片描述

Let’s also move the scripts to a new scripts folder just to keep them clean:

在这里插入图片描述

Edit the borders.cs script:


using UnityEngine;
using System.Collections;

public class Borders : MonoBehaviour {

    // Use this for initialization
    void Start () {

    }

    // Update is called once per frame
    void Update () {

    }
}
We don't need to start or update functions, so let's remove them. Instead, we will use the ontriggerenter2d function. Whenever something enters one of the boundary triggers, unified will automatically call the function:

using UnityEngine;
using System.Collections;

public class Borders : MonoBehaviour {

    void OnTriggerEnter2D(Collider2D co) {

    }
}
In this function, no matter what enters triggers, we will destroy the object:

using UnityEngine;
using System.Collections;

public class Borders : MonoBehaviour {

    void OnTriggerEnter2D(Collider2D co) {
        Destroy(co.gameObject);
    }
}
After saving the script, our boundary is completed. We will see later that if we try to shoot a bird out of the level, it will disappear.

4. Cloud setting

We will spend a few minutes adding additional clouds to the background to make the level look better. As usual, let’s draw one first:

在这里插入图片描述

Let’s in the project area and thenInspectorTo modify cloud import settings:

在这里插入图片描述

Now what we need to do is to enter the scene from the project area several times and place each cloud in the position we want:

在这里插入图片描述

Note: as long as we use some repeated patterns and some very colors, we can make the level look quite good without much effort.

5. Catapult design

Catapult picture

在这里插入图片描述

A missile will generate new birds and allow the user to launch to the level. As usual, we’ll start with sprites:
Here are the import settings:

在这里插入图片描述

Later, we will create a script to generate a new bird at the position of the slingshot, or to be exact, a bird at the pivot position of the slingshot.
We want to appear at the top of the slingshot instead of in the middle, which is why we set pivot at the top in the “import settings”.

The following image shows the center and top:

在这里插入图片描述

*Note: if we set pivot as the center and then change the point whose position is the center of the slingshot. If we set pivot as the top, and then change the position to the point at the top of the slingshot.

Well, now we can drag the catapult into the scene (- 22, 3):

在这里插入图片描述

Generate bird script
As mentioned earlier, our slingshot should be a generative bird. Specifically, it should generate one at the beginning, wait for the user to start it, and then generate another after all the physical calculations are completed. When nothing moves

We can implement this behavior through scripts.
Add script spawn.cs:

在这里插入图片描述

We can double-click the script to open it:


using UnityEngine;
using System.Collections;

public class Spawn : MonoBehaviour {

    // Use this for initialization
    void Start () {

    }

    // Update is called once per frame
    void Update () {

    }
}
This startup function is automatically called by unity at the beginning of the game. This update function is automatically called again and again, about 60 times per second. We don't need any of them so we can remove them from the script.

There is another type of update function, which is called fixedupdate… It is also called again and again, but it is calculated within the same time interval of unit physics, so it is a good idea to use fixedupdate when doing physical work (we will do so soon)

The following is the modified fixedupdate script:


using UnityEngine;
using System.Collections;

public class Spawn : MonoBehaviour {

    void FixedUpdate() {

    }
}
OK, let's add a variable that allows us to specify birdprefab later:

using UnityEngine;
using System.Collections;

public class Spawn : MonoBehaviour {
    // Bird Prefab that will be spawned
    public GameObject birdPrefab;

    void FixedUpdate() {

    }
}
Here is how we generate it:

void spawnNext() {
    // Spawn a Bird at current position with default rotation
    Instantiate(birdPrefab,transform.position,Quaternion.identity);
}
Generated trigger area

Now we can’t just have one bird after another. Instead, we will have to generate one and wait for it to be launched. There are several ways to do this, but the easiest way is to use triggers

Trigger is a simple collider that receives collision information, but it is not actually a part of the physical world. So if we add a trigger, then we will be notified whenever something enters, stays in or leaves trigger. However, because it’s just a trigger, things won’t collide with it like ordinary Collider (which will soon make more sense)

We can add the trigger to the catapult by clicking the add component circle collider 2D in the hierarchy panel, giving it an appropriate radius and center, and then enabling the trigger:

Is Trigger

在这里插入图片描述

We can also view in the scene:

在这里插入图片描述

After adding the trigger, we will be notified whenever something enters. (ontriggerenter2d), stay (ontriggerstay2d) or leave (ontriggerexit2d) the green circle above.

Now, we can create a variable in use and set it to bool value, which is false when giving birth to a bird and true when it leaves the trigger:


using UnityEngine;
using System.Collections;

public class Spawn : MonoBehaviour {
    // Bird Prefab that will be spawned
    public GameObject birdPrefab;

    // Is there a Bird in the Trigger Area?
    bool occupied = false;

    void FixedUpdate() {

    }

    void spawnNext() {
        // Spawn a Bird at current position with default rotation
        Instantiate(birdPrefab, transform.position, Quaternion.identity);
        occupied = true;
    }

    void OnTriggerExit2D(Collider2D co) {
        // Bird left the Spawn
        occupied = false;
    }
}
Then we can modify our fixedupdate function, so whenever the trigger area is no longer occupied, it always generates a bird:

void FixedUpdate() {
    // Bird not in Trigger Area anymore?
    if (!occupied)
        spawnNext();
}
Note:! Occupied means not occupied... We can also use if (occupied = = false)

Our build script is now working, but let’s add another feature. After shooting a bird, many things collide with each other, fall, roll around, and even explode. In the original “angry birds” game, a new bird will be produced only after everything on the level stops moving.

We can easily create a scenemoving function to find out whether any objects in the scene are still moving, not just a little:


bool sceneMoving() {
    // Find all Rigidbodies, see if any is still moving a lot
    Rigidbody2D[] bodies = FindObjectsOfType(typeof(Rigidbody2D)) as Rigidbody2D[];
    foreach (Rigidbody2D rb in bodies)
        if (rb.velocity.sqrMagnitude > 5)
            return true;
    return false;
}
Note: we use findobjectsoftype to find all objects with rigid bodies, and then we will check the velocity of each object. If the sqrmagnitude of the rigid body is greater than 5, it means that the rigid body is still moving, it will return true, and if not, it will return false

Using this neat little script, we can easily modify the fixedupdate function, so new birds will be generated only without any movement:


void FixedUpdate() {
    // Bird not in Trigger Area anymore? And nothing is moving?
    if (!occupied && !sceneMoving())
        spawnNext();
}
Now that we have completed the script for generating birds, we can see the script mounted on the slingshot on the inspector panel:

在这里插入图片描述

Note: we can’t test the generated bird script without birds yet, but it does work well, and we’ll see this after creating birds.

6. Bird setting

Pictures of birds
Let’s start with something more interesting: birds. We first draw a 16 x 16 pixel image of a bird with a large round body and some small wings and eyes:

在这里插入图片描述

We will import settings for this using the following method:

在这里插入图片描述

Let’s enter the scene from the project area. To create game objects from it:

在这里插入图片描述

Physics of birds

Let’s add a collider circle collider 2D for birds:

在这里插入图片描述

Now there is a gap in the physics material 2D Collider, so that we can give birds some special physical properties. In the “unity angry birds” tutorial, physical materials will be very useful, because now, if the bird falls to the ground, it will look like this:

在这里插入图片描述

It looks a little unnatural. Instead, we want the bird to jump out of the following things:

在这里插入图片描述

To create a bouncing effect in the second picture, all we have to do is in the project area and select Create > physics2d material, say the bird material and turn it into a new physical material folder:

在这里插入图片描述

Once selected, we can modify itInspector:

在这里插入图片描述

Note: the greater the bounce value, the more the bird will bounce.

Finally, we can select the bird again, and then drag the bird material from the project area into the collider material slot:

在这里插入图片描述

The bird should also walk around. A rigid body is responsible for the gravity, velocity and other forces that make an object move. According to the rule of thumb, in the physical world, everything that should move needs a rigid body:

在这里插入图片描述

Note: we set gravity scale to 4 because it can make birds fly faster.

If we press play, now we can see the bird fall off the ground and bounce up:

在这里插入图片描述

Our bird physics has been completed, but there is a small adjustment that we must make here. Now, if we generate it in the catapult, it will immediately fall to the ground due to its rigid body gravity. We only hope that the bird will be affected by gravity as soon as the user fires, so let’s enable is kinematic now and disable it in the script:

在这里插入图片描述

Now, the rigid body is kinematic, which means that it is not affected by gravity or velocity, so it will not fall immediately.

Note: to illustrate this more clearly, anything like a hero, car or bird should have a rigid body that is kinematic. We can only make the bird move as long as it is still in the slingshot.

Bird preform
As mentioned earlier, this bird should not appear in the scene from the beginning. Instead, slingshot should generate a new bird when needed. In order for the slingshot to generate birds, we must create a preform (in other words, we must have bird resources in our project area)

To create a preform, all we have to do isHierarchy panel, drag the object into the prefabs folder in the project area:

在这里插入图片描述

Now, we can load birds into the scene at any time, which means that we can now also load birds from the sceneHierarchyDelete this object from:

在这里插入图片描述

Generative bird
Let’s drag the preform bird to the birdprefab slot in the script of our spawn.cs:

在这里插入图片描述

If we press play, now we can see how the catapult produces a bird:

在这里插入图片描述

Pull and release script
The user should be able to put the bird around the slingshot and release it to shoot it in the desired direction.

We will create a new c# script named pullandrelease:


using UnityEngine;
using System.Collections;

public class PullAndRelease : MonoBehaviour {

    // Use this for initialization
    void Start () {

    }

    // Update is called once per frame
    void Update () {

    }
}
The user will be able to drag the bird around a circle. Each circle needs a center. In our example, it is the generation position of the bird, so let's make sure to save it in a variable:

using UnityEngine;
using System.Collections;

public class PullAndRelease : MonoBehaviour {
    // The default Position
    Vector2 startPos;

    // Use this for initialization
    void Start () {
        startPos = transform.position;
    }
}
*Note: we also removed the update function because we don't need it.

OK, in order for the user to drag the bird into a circle, we must find out whether the bird has been clicked. (to be exact: drag)… We also need to know whether the user has released the mouse. In this case, we must launch the bird in our target direction.

Of course, if there is no such function, it is not unity. Unity automatically calls the onmouseup and onmousedrag functions. When we drag the game object with the mouse or release the mouse later:

*Note: mouse drag means that the user presses and holds the mouse button on the GameObject and then moves the mouse.

It’s really easy to move birds. All we have to do is change the current mouse position to a point in the game world, and then move the bird there. Of course, only within a certain radius:

void OnMouseDrag() {    // Convert mouse position to world position    Vector2 p= Camera.main.ScreenToWorldPoint(Input.mousePosition);    // Keep it in a certain radius    float radius = 1.8f;    Vector2 dir = p - startPos;    if (dir.sqrMagnitude > radius)        dir = dir.normalized * radius;    // Set the Position    transform.position = startPos + dir;}

*Note: we can use screentoworldpoint to get the position where the finger clicks, but this position is not fixed. After finding the position P where the finger clicks, we only need to calculate the distance from startpos to P. if the distance is too long dir. Sqrmagnitude > radius, let this position equal to a maximum value dir = dir. Normalized * radius

If we press play, then we can circle the bird:

在这里插入图片描述

It’s just as easy to shoot a bird in one direction. We can use our onmouseup function to know when the mouse is released. Then, we will calculate from bird to startpos, and then use addforce of rigidbody to start its function there:

// The Force added upon releasepublic float force = 1300;void OnMouseUp() {    // Disable isKinematic    GetComponent<Rigidbody2D>().isKinematic = false;    // Add the Force    Vector2 dir = startPos - (Vector2)transform.position;    GetComponent<Rigidbody2D>().AddForce(dir * force);    // Remove the Script (not the gameObject)    Destroy(this);}

*Note: as mentioned earlier, we will also disable kinematics to make the rigid body affected by gravity and velocity again. We just subtract startpos from the current position… Finally, we delete the object so that it can no longer be launched.

If we press play, then we can pull the bird and fire:

在这里插入图片描述

Feather particle effect
Let’s make the game smoother by increasing the collision effect of birds. Once it lands for the first time, it should grow feathers around itself like this:

在这里插入图片描述

When we need random particles to generate, rotate and move in a certain direction, we use particle system. A simple example of a particle system is smoke, which produces a gray texture and then moves up in a cone.

We will modify our particle system so that instead of making particles fly up, we will make them fly in all directions. We will also modify some more specific things, such as size, speed and rotation. Our feather doesn’t have the right or wrong particle system, so you can use it at will until it looks like you want it to. Here are our conclusions:

在这里插入图片描述

This is the image we use to do this:

在这里插入图片描述

*Note: right click the image and select Save As. And save it in the assets / sprites folder of the project.

Import settings:

在这里插入图片描述

After that, we can enter our particle system from the project area, so it uses images for all particles.

Now we can drag the feather objects in the scene to the prefabs folder in our project area to make a preform:

在这里插入图片描述

Then we can delete the feather game object in hierarchy

The last thing is to add a script to our bird so that the feather particle system will be generated in case of collision. Let’s create a new script in the project area… Let’s name it collisionspawnonce. We will also move it to our sprits folder and double-click it to open it:


using UnityEngine;
using System.Collections;

public class CollisionSpawnOnce : MonoBehaviour {

    // Use this for initialization
    void Start () {

    }

    // Update is called once per frame
    void Update () {

    }
}
We do not need to start or update functions. Instead, we will use the oncollisionenter2d function and effect to generate the variables of the preform that the public game object should generate:

using UnityEngine;
using System.Collections;

public class CollisionSpawnOnce : MonoBehaviour {
    // Whatever should be spawned (Particles etc.)
    public GameObject effect;

    void OnCollisionEnter2D(Collision2D coll) {
        // Spawn Effect, then remove Script
        Instantiate(effect,transform.position,Quaternion.identity);
        Destroy(this);
    }
}
*Note: to ensure that the effect is produced only once, we will start from destroy (this) (this will only close the script, not the whole bird).

After saving the script, we can see the effect slot… Now we can drag the feather particle system preform project area into the effect slot:

在这里插入图片描述

If we press play and launch the bird to the ground, then we can see that the feathers around it are generating:

在这里插入图片描述

route
We will also add another effect to our bird to make it look smoother: a track of white dots to show the track of the bird:

在这里插入图片描述

First, we need some tracking images of different sizes:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

We will use the same import settings for each image:

在这里插入图片描述

We want to be able to generate the trajectory part at any time we want, which means we will need three preforms. So let’s select three images and drag them into the scene, then drag them back to the prefabs folder. Until we have three preforms:

在这里插入图片描述

Now we only need a script to generate one trail element after another, about once a second. Let’s create a new c# script and name it Trail:


using UnityEngine;
using System.Collections;

public class Trail : MonoBehaviour {

    // Use this for initialization
    void Start () {

    }

    // Update is called once per frame
    void Update () {

    }
}
We can remove the update because we don't need it. Let's add a public GameObject [] variable that holds all trace elements. We will use array, which means that it is not just a GameObject:

using UnityEngine;
using System.Collections;

public class Trail : MonoBehaviour {

    // Trail Prefabs
    public GameObject[] trails;

    // Use this for initialization
    void Start () {

    }
}
We also need a function to generate the next clue. For example, it should generate the first trail element, and then the next time it should generate the second, then the third, and then the first. This can be done by using instantiation with an additional counter variable:

using UnityEngine;
using System.Collections;

public class Trail : MonoBehaviour {

    // Trail Prefabs
    public GameObject[] trails;
    int next = 0;

    // Use this for initialization
    void Start () {

    }

    void spawnTrail() {
        Instantiate(trails[next], transform.position, Quaternion.identity);
        next = (next+1) % trails.Length;
    }
}
We set it to 0, which means that the first element in trails spawntrail is called. Then use next + 1 to add next. To keep it in the range of the tracks array, we will also use% tracks. Length, which uses modulus (%) operation. For those who do not understand the module, here is a more obvious version:

void spawnTrail() {
    Instantiate(trails[next], transform.position, Quaternion.identity);
    next = next + 1;
    if (next == trails.Length) next = 0;
}
Now we have a track generation function. We can use it to generate a new track element. By using the invokerepeting function for 100 ms, we can generate one:

using UnityEngine;
using System.Collections;

public class Trail : MonoBehaviour {

    // Trail Prefabs
    public GameObject[] trails;
    int next = 0;

    // Use this for initialization
    void Start () {
        // Spawn a new Trail every 100 ms
        InvokeRepeating("spawnTrail", 0.1f, 0.1f);
    }

    void spawnTrail() {
        Instantiate(trails[next], transform.position, Quaternion.identity);
        next = (next+1) % trails.Length;
    }
}
Now, path elements are always generated, even when birds don't fly. Let's add a small modification. The track will be generated only when the bird flies fast enough:

void spawnTrail() {
    // Spawn Trail if moving fast enough
    if (GetComponent<Rigidbody2D>().velocity.sqrMagnitude > 25) {
        Instantiate(trails[next], transform.position, Quaternion.identity);
        next = (next+1) % trails.Length;
    }
}
OK, let's save the script. Here, we will drag from our three small-diameter preforms into the slot:

在这里插入图片描述

If we press play, then we can see the trace of the bird after shooting:

在这里插入图片描述

7. Wood chips

Let’s add some structures such as stone, ice and wood to enrich our unity2d angry birds game.

Let’s draw a piece of wood first:

在这里插入图片描述

Note: right click the image and select Save as. And save it in the assets / sprits folder of the project.

Here are the import settings:

在这里插入图片描述

Now we can drag it to the scene and put it somewhere on the ground:

在这里插入图片描述

Wood chips should be part of the physical world, so we will continue to add box collider 2D components:

在这里插入图片描述

Wood chips should also be able to move around. Now it won’t move by itself, but if the bird flies into it, it will move. It should also be affected by gravity, so what we need is a rigid body… We can select Add component – > physical 2D – > rigidbody 2D… We will also increase mass to 4, so it is a little heavier:

在这里插入图片描述

Now we have a piece of wood, which is part of the physical world!

For this slightly different wood chip, we will repeat the same workflow:

在这里插入图片描述

This is how our game looks at adding the second piece of wood and rotating the first 90 °:

在这里插入图片描述

8. Stone

In order to have several different structures in our game, we will also add two different types of stones:

在这里插入图片描述

在这里插入图片描述

The operation process is the same as before. This time, we set mass to 10:

在这里插入图片描述

Here are some stones in our game:

在这里插入图片描述

Note: we again achieved some decent appearance with basic shapes, only a few colors and jitter.

9. Ice

Picture of ice
We will add a structure to our game: ice. But this time it will be more interesting.

As usual, we first draw a piece of ice:

在这里插入图片描述

This import setting is the same as before:

在这里插入图片描述

Ice physics
Add boxcollider2d rigid body component:

在这里插入图片描述

Ice should be very slippery, so let’s right-click the project area and select Create – > physical 2D material to give it a name ICE icematerial:

在这里插入图片描述

Set parameters:

在这里插入图片描述

After that, we can select ice in the hierarchy panel and drag icematerial from the project area to the boxcollider2d > material slot:

在这里插入图片描述

Destroy ice on Impact
If we are hit by enough force, we also want the ice to be destroyed, because this is the natural function of ice. We added the script breakonimpact.cs:


using UnityEngine;
using System.Collections;

public class BreakOnImpact : MonoBehaviour {

    // Use this for initialization
    void Start () {

    }

    // Update is called once per frame
    void Update () {

    }
}
We don't need to start or update functions, so let's remove these two functions. We need a way to estimate the force of collision. We will keep it simple and multiply speed by mass:

float collisionForce(Collision2D coll) {
    // Estimate a collision's force (speed * mass)
    float speed = coll.relativeVelocity.sqrMagnitude;
    if (coll.collider.GetComponent<Rigidbody2D>())
        return speed * coll.collider.GetComponent<Rigidbody2D>().mass;
    return speed;
}
*Note: collision2d inherits the oncollisionenter2d function. We will obtain an estimated collision force, which contains the multiplication of direction and velocity. If we only care about velocity, we can use col.relativevelocity.sqrmagnitude... Now, if the object causing the collision has a rigid body, then we multiply the velocity by the mass of the rigid body... Otherwise, we only return the velocity.

Well, now we can use the oncollisionenter2d function to get notification about collisions. Then, we will compare the collision force with a configurable variable. If it is strong, the ice will break:


using UnityEngine;
using System.Collections;

public class BreakOnImpact : MonoBehaviour {
    public float forceNeeded = 1000;

    float collisionForce(Collision2D coll) {
        // Estimate a collision's force (speed * mass)
        float speed = coll.relativeVelocity.sqrMagnitude;
        if (coll.collider.GetComponent<Rigidbody2D>())
            return speed * coll.collider.GetComponent<Rigidbody2D>().mass;
        return speed;
    }

    void OnCollisionEnter2D(Collision2D coll) {
        if (collisionForce(coll) >= forceNeeded)
            Destroy(gameObject);
    }
}
If we save the script, press play to hit the bird against the ice, and then it will break:

在这里插入图片描述

Now, we can take a few minutes to copy these structures and put them together so that we can add pigs between them:

在这里插入图片描述

10. Green pig

Birds want to destroy all pigs, so let’s add some pigs to our game so that birds won’t feel bored.

Let’s first draw a:

在这里插入图片描述

Import settings:

在这里插入图片描述

Add colliders and rigid bodies:

在这里插入图片描述

If there is enough force to attack the pig, the pig will die. Fortunately, we already have a script. Add the script breakonimpact.cs to our pig object and set the value of force needed:

在这里插入图片描述

*Note: the ability to reuse such scripts is component-based development.

Now we can copy the pig and move it between some structures:

在这里插入图片描述

If we press play, then we can try to kill pigs:

在这里插入图片描述

11. Rubber

We’re going to add one last feature to our game: slingshot rubber, so dragging and releasing birds look much better:

在这里插入图片描述

We first draw half of the rubber, which is almost just a thick line:

在这里插入图片描述

Here are the import settings:

在这里插入图片描述

*Note: this time we set pivot to the right (side), which makes some rotation easier.

Now we can enter the scene twice from the project area, name one left rubber and the other right rubber, and put them on the upper part of the slingshot:

在这里插入图片描述

We need to make sure the one on the left is always drawn. The rear and right slingshots are always pulled in. Part of the front. We can add two more classification layers for our game, but we will keep it simple. Just change the sequence to – 1 rubber on the left and 1 rubber on the right:

在这里插入图片描述

在这里插入图片描述

Now the rubber looks like an external slingshot:

在这里插入图片描述

Before we start scripting, let’s set these two objects as children of slingshot in hierarchy:

在这里插入图片描述

*Note: whenever we move the slingshot, the rubber parts move with it.

Let’s create a new c# script and name it rubber:


using UnityEngine;
using System.Collections;

public class Rubber : MonoBehaviour {

    // Use this for initialization
    void Start () {

    }

    // Update is called once per frame
    void Update () {

    }
}
The purpose of this script is to make the two rubber parts follow the bird until it leaves the trigger ring of the generated bird.

We need two variables, leftrubber and rightrubber. Let’s specify rubber later. We don’t need to start or update functions. Let’s delete them:


using UnityEngine;
using System.Collections;

public class Rubber : MonoBehaviour {
    // The Rubber objects
    public Transform leftRubber;
    public Transform rightRubber;
}
Now, there are some slightly more complex functions. We will need a function to position the rubber on the slingshot and bird. We must first rotate the rubber to the direction of the bird, and then make the rubber become or shorter according to the distance of the bird:

void adjustRubber(Transform bird, Transform rubber) {
    // Rotation
    Vector2 dir = rubber.position - bird.position;
    float angle = Mathf.Atan2(dir.y, dir.x) * Mathf.Rad2Deg;
    rubber.rotation = Quaternion.AngleAxis(angle, Vector3.forward);

    // Length
    float dist = Vector3.Distance(bird.position, rubber.position);
    dist += bird.GetComponent<Collider2D>().bounds.extents.x;
    rubber.localScale = new Vector2(dist, 1);
}
Note: first we calculate the distance from the bird to the rubber, and then calculate the angle in this direction. Then, we rotate the rubber to this angle through quaternion. Angle axis (angle, vector3. Forward). Finally, we calculate the distance from the bird to the rubber, and then we set the scale of the rubber to this distance plus the length of X of the collider, namely dist + = bird. Getcomponent(). Bounds. Extents. X

This ontriggerstay2d function will tell us that whenever the bird changes its position, it is still slingshot. We can use this function to adjust the left and right rubber bands:


using UnityEngine;
using System.Collections;

public class Rubber : MonoBehaviour {
    // The Rubber objects
    public Transform leftRubber;
    public Transform rightRubber;

    void adjustRubber(Transform bird, Transform rubber) {
        // Rotation
        Vector2 dir = rubber.position - bird.position;
        float angle = Mathf.Atan2(dir.y, dir.x) * Mathf.Rad2Deg;
        rubber.rotation = Quaternion.AngleAxis(angle, Vector3.forward);

        // Length
        float dist = Vector3.Distance(bird.position, rubber.position);
        dist += bird.GetComponent<Collider2D>().bounds.extents.x;
        rubber.localScale = new Vector2(dist, 1);
    }

    void OnTriggerStay2D(Collider2D coll) {
        // Stretch the Rubber between bird and slingshot
        adjustRubber(coll.transform, leftRubber);
        adjustRubber(coll.transform, rightRubber);
    }
}
It's almost ready. We will add another event triggered when leaving to make the rubber band shorter after launch:

void OnTriggerExit2D(Collider2D coll) {
    // Make the Rubber shorter
    leftRubber.localScale = new Vector2(0, 1);
    rightRubber.localScale = new Vector2(0, 1);
}
Now, we can select the game object in the slingshot object first. Hierarchy, then click Add component - > scitps - > Rubber... We will also drag these two rubbers into the corresponding slots:

在这里插入图片描述

If we press play, now we can see the rubber band between the bird and the slingshot:

在这里插入图片描述

Of course, now we can also play a round of angry birds:

在这里插入图片描述

summary

Here is the end of this article. We have just created a small game, angry birds, which uses simple shapes and colors to achieve a good effect. Unity’s 2D physics engine is widely used and many effects are added

Recommended Today

Seven solutions for distributed transactions

1、 What is distributed transaction Distributed transaction means that transaction participants, transaction supporting servers, resource servers and transaction managers are located on different nodes of different distributed systems. A large operation is completed by more than n small operations. These small operations are distributed on different services. For these operations, either all of them are […]