# 【投掷骰子】

全屏显示

十分简单的投掷骰子的小游戏,点一下按钮就能掷骰子。

这个项目对于学习Unity的新手十分合适,能学习到以下内容。

  1. 骰子的建模。
  2. 设置游戏对象位置和旋转。
  3. 基本物理碰撞和加力。
  4. 基本的场景搭建。
  5. 基本的UI按钮点击与脚本函数调用。

# 投掷的代码

Assets/Scenes/ThrowDiceScript.cs

using System.Collections;
using UnityEngine;

public class ThrowDiceScript : MonoBehaviour
{
    public GameObject[] dices;
    void Start()
    {
        if(dices != null){
            for (int i = 0; i < dices.Length; i++)
            {
                FirstRandomDice(dices[i]);
            }
        }
    }
    
    /// <summary>
    /// 按下投掷按钮
    /// </summary>
    public void onClickThrowBtn()
    {
        if(dices == null || dices.Length == 0){
            return ;
        }
        StartCoroutine(ThrowDiceCoroutine());
    }

    IEnumerator ThrowDiceCoroutine()
    {
        ThrowDice(dices[0],0);
        yield return new WaitForSeconds(0.2f);
        ThrowDice(dices[1],1);
        yield return new WaitForSeconds(0.2f);
        ThrowDice(dices[2],2);
    }

    private void FirstRandomDice(GameObject dice)
    {
        float rotationX = UnityEngine.Random.Range(0,360);
        float rotationY = UnityEngine.Random.Range(0,360);
        float rotationZ = UnityEngine.Random.Range(0,360);
        Quaternion newQ = Quaternion.Euler(rotationX,rotationY,rotationZ);

        float minY = 3.0f;
        float maxY = 6.0f;
        float xOffset = 1.0f;
        float zOffset = 1.0f;
        float xPosition = UnityEngine.Random.Range(-xOffset,xOffset);
        float yPosition = UnityEngine.Random.Range(minY,maxY);
        float zPosition = UnityEngine.Random.Range(-zOffset,zOffset);
        Vector3 pos = new Vector3(xPosition, yPosition, zPosition);

        dice.transform.SetPositionAndRotation(pos,newQ);
    }

    private void ThrowDice(GameObject dice,int index)
    {
        // 随机旋转
        float rotationX = UnityEngine.Random.Range(0,360);
        float rotationY = UnityEngine.Random.Range(0,360);
        float rotationZ = UnityEngine.Random.Range(0,360);
        Quaternion newQ = Quaternion.Euler(rotationX,rotationY,rotationZ);

        // 随机位移
        float xOffset = 1.0f;
        float zOffset = 1.0f;
        float xPosition = UnityEngine.Random.Range(-xOffset,xOffset);
        float yPosition = 8 - index;
        float zPosition = UnityEngine.Random.Range(-zOffset,zOffset);
        Vector3 pos = new Vector3(xPosition, yPosition, zPosition);
        
        dice.GetComponent<DiceScript>().SetTargetPos(pos,newQ);
    }
}

Assets/Scenes/DiceScript.cs

using UnityEngine;

/** 骰子的脚本 */
public class DiceScript : MonoBehaviour
{
    private Vector3? _targetPos = null;
    private Quaternion? _targetRotation = null;

    void Update()
    {
        // 上一帧到当前帧的间隔时间(秒)
        float deltaTime = Time.deltaTime;
        float moveDistance = 20 * deltaTime;
        if(_targetPos != null){
            Vector3 curPos = this.transform.position;
            float dist = Vector3.Distance(curPos, _targetPos??Vector3.zero);
            Rigidbody rig = this.GetComponent<Rigidbody>();
            Vector3 newPos = Vector3.MoveTowards(curPos,_targetPos??Vector3.zero,moveDistance);
            if(dist >= 0.1f)
            {
                this.transform.SetPositionAndRotation(newPos,_targetRotation??Quaternion.identity);
            }else{
                this.transform.SetPositionAndRotation(newPos,_targetRotation??Quaternion.identity);
                _targetPos = null;
                rig.useGravity = true;
                // 随机加一点点力
                float xForce = UnityEngine.Random.Range(-1,1);
                float yForce = UnityEngine.Random.Range(-1,1);
                float zForce = UnityEngine.Random.Range(-1,1);
                rig.velocity = new Vector3(xForce,yForce,zForce);
            }
        }
    }

    /// <summary>
    /// 投掷时设置目标位置
    /// </summary>
    /// <param name="targetPos"></param>
    public void SetTargetPos(Vector3 targetPos,Quaternion targetRotation)
    {
        if(_targetPos == null)
        {
            _targetPos = targetPos;
            _targetRotation = targetRotation;
            Rigidbody rig = this.GetComponent<Rigidbody>();
            rig.useGravity = false;
            rig.rotation = targetRotation;
        }
    }
}

# 骰子模型的制作

建立一个骰子模型的思路,先建立高精细模型,用于创建法线贴图。再使用PS创建一个AO贴图。

高精细模型

  1. 正方形
  2. 对面进行圆角
  3. 建立一些球体进行布尔运算
  4. UV映射

低模

  1. 正方形
  2. UV映射
  3. 创建纹理和材质

使用Maya以下功能进行烘培法线贴图:

Markdown 图片

Markdown 图片