笔记-【游戏制作教程】30分钟制作一款游戏 (1)【Unity】

本文只记录重要知识点以及涉及到的脚本 API,详细教学过程:视频链接

本文中大量关于 API 的描述来自 Unity 官方文档

另:学完之后发现这个教程非常非常像这个 Unity 官方教程

0. 搭建场景

这个简单的场景需要一个平面、四堵墙、一个球体作为玩家操控的对象,以及七个待收集的小方块。

搭完的场景如下所示:
在这里插入图片描述

1. 用方向键操纵球

首先需要为球添加刚体组件(Rigidbody),并为其挂载一个脚本,关键代码如下:

    Rigidbody rigid;
    float speed = 0.5f;
    
    void Start()
    {
        rigid = GetComponent<Rigidbody>();		// 获取刚体组件
    }

    void Update()
    {
        var h = Input.GetAxis("Horizontal");    // 取值范围 -1 到 1,代表从左到右
        var v = Input.GetAxis("Vertical");      // 取值范围 -1 到 1,代表从下到上

        var movement = new Vector3(h, 0, v);

        rigid.AddForce(movement * speed);
    }

新学到的 API:

Input.GetAxis

public static float GetAxis(string axisName);

Returns the value of the virtual axis identified by axisName.

The value will be in the range -1…1 for keyboard and joystick input.

那么有哪些轴可以调用呢?在 Unity 中点击 Edit -> Project Settings -> Input Manager 就能查看所有的轴以及键位,这段代码中就使用了HorizontalVertical,对应的键位是 wasd 或者方向键。


Rigidbody.AddForce

public void AddForce(Vector3 force, ForceMode mode = ForceMode.Force);

Adds a force to the Rigidbody.

Force is applied continuously along the direction of the force vector. Specifying the ForceMode mode allows the type of force to be changed to an Acceleration, Impulse or Velocity Change.

以下是可以使用的ForceMode,默认使用 Force:

成员描述
ForceAdd a continuous force to the rigidbody, using its mass.
AccelerationAdd a continuous acceleration to the rigidbody, ignoring its mass.
ImpulseAdd an instant force impulse to the rigidbody, using its mass.
VelocityChangeAdd an instant velocity change to the rigidbody, ignoring its mass.

例如要使用 VelocityChange:
rigid.AddForce(movement * speed, ForceMode.VelocityChange);


2. 让小方块随时间匀速自转

为所有小方块挂载同样的脚本,关键代码如下:

    void Update()
    {
        transform.Rotate(new Vector3(15, 30, 45) * Time.deltaTime);
    }

transform.Rotate

public void Rotate(Vector3 eulers, Space relativeTo = Space.Self);

参数描述
eulersThe rotation to apply.
relativeToThe rotation axes, which can be set to local axis (Space.Self) or global axis (Space.World)

public void Rotate(float xAngle, float yAngle, float zAngle, Space relativeTo = Space.Self);

参数描述
relativeToDetermines whether to rotate the GameObject either locally to the GameObject or relative to the Scene in world space.
xAngleDegrees to rotate the GameObject around the X axis.
yAngleDegrees to rotate the GameObject around the Y axis.
zAngleDegrees to rotate the GameObject around the Z axis.

The implementation of this method applies a rotation of zAngle degrees around the z axis, xAngle degrees around the x axis, and yAngle degrees around the y axis (in that order).

Rotate can have the euler angle specified in 3 floats for x, y, and z.


Time.deltaTime

The completion time in seconds since the last frame (Read Only).

This property provides the time between the current and previous frame.

借助这个只读变量,就可以让小方块在每一秒的转动角度是相等的,而不是每一帧的转动角度相等。(通常每秒帧数随不同机器和时间而变化)


3. 当球碰撞到小方块时,让小方块消失

需要在球的脚本中加入下面这个函数:

    private void OnTriggerEnter(Collider other)
    {	// 这里用所有小方块都有的脚本组件来判断撞到的物体是否是小方块
    	// 个人觉得用标签来识别是更好的做法
    	// 总之用所有小方块共有的一个属性来识别即可
        if (other.GetComponent<Pickup>())
        {
            other.gameObject.SetActive(false);
        }
    }

Collider.OnTriggerEnter

Parameters
other: The other Collider involved in this collision.

When a GameObject collides with another GameObject, Unity calls OnTriggerEnter.

OnTriggerEnter happens on the FixedUpdate function when two GameObjects collide. The Colliders involved are not always at the point of initial contact.

Note: Both GameObjects must contain a Collider component. One must have Collider.isTrigger enabled, and contain a Rigidbody. If both GameObjects have Collider.isTrigger enabled, no collision happens. The same applies when both GameObjects do not have a Rigidbody component.

根据上述官方文档的描述,我们的球和小方块都需要有 Collider 组件,且只能有其中一方激活 Collider.isTrigger。在这个例子中我们将所有小方块的 isTrigger 激活。


gameObject.SetActive

public void SetActive(bool value);

Activates/Deactivates the GameObject, depending on the given true or false value.

A GameObject may be inactive because a parent is not active. In that case, calling SetActive will not activate it, but only set the local state of the GameObject, which you can check using GameObject.activeSelf. Unity can then use this state when all parents become active.

Deactivating a GameObject disables each component, including attached renderers, colliders, rigidbodies, and scripts.


4. 添加记分板和胜利条件

在小球脚本中的关键代码:

    public UnityEngine.UI.Text tips;
    int count = 0;

    private void OnTriggerEnter(Collider other)
    {
        if (other.GetComponent<Pickup>())
        {
            other.gameObject.SetActive(false);
            ++count;
            RefreshTips();	// 仅在碰撞时调用
        }
    }
    void RefreshTips()	// 自定义的函数,刷新记分板
    {
        tips.text = "Count: " + count.ToString();
        if (count >= 7)
        {
            tips.text = "Win!";
        }
    }

需要在界面上新建一个 Canvas,在其中新建一个 Text,并将这个 Text 挂载到小球脚本的 tips 变量上面。


5. 脚本代码总览

5.1 小球脚本Player.cs

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

public class Player : MonoBehaviour
{
    public UnityEngine.UI.Text tips;
    Rigidbody rigid;
    float speed = 0.5f;
    int count = 0;
    // Start is called before the first frame update
    void Start()
    {
        rigid = GetComponent<Rigidbody>();
    }

    // Update is called once per frame
    void Update()
    {
        var h = Input.GetAxis("Horizontal");    // 取值范围 -1 到 1,代表从左到右
        var v = Input.GetAxis("Vertical");      // 取值范围 -1 到 1,代表从下到上

        var movement = new Vector3(h, 0, v);

        rigid.AddForce(movement * speed, ForceMode.VelocityChange);
    }
    private void OnTriggerEnter(Collider other)
    {
        if (other.GetComponent<Pickup>())
        {
            other.gameObject.SetActive(false);
            ++count;
            RefreshTips();
        }
    }
    void RefreshTips()
    {
        tips.text = "Count: " + count.ToString();
        if (count >= 7)
        {
            tips.text = "Win!";
        }
    }
}

5.2 方块脚本Pickup.cs

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

public class Pickup : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        transform.Rotate(new Vector3(15, 30, 45) * Time.deltaTime);
    }
}

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值