unity入门项目Ruby‘s Adventure

这篇具有很好参考价值的文章主要介绍了unity入门项目Ruby‘s Adventure。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

Ruby's Adventure是unity官方提供的一个案例,当初入门就是做的这个项目,学到了很多unity的基本操作。这篇文章记录了这个游戏从创建项目到发布的过程。

游戏简介:城镇里的机器人都因为缺少零件而失控,我们的主角狐狸Ruby收到青蛙先生的委托后,拿上了齿轮,去修复失控的机器人。

一、游戏效果

玩家可以用W、A、S、D控制Ruby移动,Ruby在触碰到失控的机器人和陷阱后生命值会降低,在和青蛙先生对话后可以按H发射齿轮,齿轮命中机器人后机器人会被修好。

unity入门项目Ruby‘s Adventure,unity,游戏引擎,c#,游戏,Powered by 金山文档
unity入门项目Ruby‘s Adventure,unity,游戏引擎,c#,游戏,Powered by 金山文档
unity入门项目Ruby‘s Adventure,unity,游戏引擎,c#,游戏,Powered by 金山文档

二、前期准备

1.创建项目

用Unity Hub创建一个2d项目

unity入门项目Ruby‘s Adventure,unity,游戏引擎,c#,游戏,Powered by 金山文档

2.资源导入

在Unity官方的AssetStore可以免费获取资源

unity入门项目Ruby‘s Adventure,unity,游戏引擎,c#,游戏,Powered by 金山文档

获取资源后可以在Unity的Package Manager中导入资源

unity入门项目Ruby‘s Adventure,unity,游戏引擎,c#,游戏,Powered by 金山文档

三、人物创建

3.1创建人物和脚本

拖入主角Ruby的图片素材,拖入的物体叫精灵(sprite)

unity入门项目Ruby‘s Adventure,unity,游戏引擎,c#,游戏,Powered by 金山文档

新建一个脚本RubyController并挂载在人物上,然后就可以写脚本来控制Ruby了。

unity入门项目Ruby‘s Adventure,unity,游戏引擎,c#,游戏,Powered by 金山文档

在visula studio中可以看到,Unity会自动生成RubyController类,并有Start()和Update()两个函数,Start()会在项目的第一帧调用一次,Update()会在之后的每一帧调用一次

unity入门项目Ruby‘s Adventure,unity,游戏引擎,c#,游戏,Powered by 金山文档

3.2实现主角的移动

获取键盘输入,并用rigidbody2d移动主角,这样在按下W、A、S、D后Ruby就会移动了

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

public class RubyController : MonoBehaviour
{
    private Rigidbody2D rigidbody2d;
    // Start is called before the first frame update
    void Start()
    {
        rigidbody2d = GetComponent<Rigidbody2D>();
    }

    // Update is called once per frame
    void Update()
    {
        //获取键盘的轴向输入
        float horizontal = Input.GetAxis("Horizontal");
        float vertical = Input.GetAxis("Vertical");
        //创建一个position记录移动后的位置
        Vector2 position = transform.position;
        //改变x,y轴上位置
        position.x = position.x + 3 * horizontal * Time.deltaTime;
        position.y = position.y + 3 * vertical * Time.deltaTime;
        //将主角的位置置为移动后的位置
        rigidbody2d.MovePosition(position);
    }
}

四、场景布局

4.1背景布置

为了能够快速布置游戏背景,可以用Tilemap工具来构建瓦片地图,创建瓦片地图时,Grid组件自动作为瓦片地图的父级,相比于传统使用图片搭建地图的方式,使用瓦片地图用来搭建地图更快。

unity入门项目Ruby‘s Adventure,unity,游戏引擎,c#,游戏,Powered by 金山文档

添加后发现场景上出现了很多格子,可以使用Tile Palette里的Tile在上面绘制,Tilemap可以理解为画布,Tile Palette可以理解为调色板,Tile就是调色板上的颜料。

unity入门项目Ruby‘s Adventure,unity,游戏引擎,c#,游戏,Powered by 金山文档

现在Tilemap中还没有Tile,先将资源切割,添加到Tile Palette中

unity入门项目Ruby‘s Adventure,unity,游戏引擎,c#,游戏,Powered by 金山文档
unity入门项目Ruby‘s Adventure,unity,游戏引擎,c#,游戏,Powered by 金山文档

然后用Tile Palette就可以方便的绘制2D场景了

unity入门项目Ruby‘s Adventure,unity,游戏引擎,c#,游戏,Powered by 金山文档

4.2设置渲染层级

我们看到背景覆盖了我们的主角Ruby,导致我们看不到我们的Ruby了,因为它们的Order in Layer都是0

为了让Ruby在背景之上,将Tilemap的Order in Layer设为-10,因为背景一定在最下面

unity入门项目Ruby‘s Adventure,unity,游戏引擎,c#,游戏,Powered by 金山文档

4.3丰富游戏场景

游戏只有背景显然是不够的,拖入更多装饰物,使场景更加丰富

unity入门项目Ruby‘s Adventure,unity,游戏引擎,c#,游戏,Powered by 金山文档

4.4控制渲染顺序

如果Ruby站在一个物体的前面,Ruby应该会挡住它,如果站在后面,则会被挡住

为了实现这个功能,可以根据y轴控制渲染顺序,在Project Settiing中改变Graphics的参数

unity入门项目Ruby‘s Adventure,unity,游戏引擎,c#,游戏,Powered by 金山文档

把sprite sort point设置为pivot(默认是中心),并将pivot放在一个合适的位置

以盒子为例,更改pivot到最下面,因为在那个点之下的物体会在盒子之前显示,之后的会被盒子挡住

unity入门项目Ruby‘s Adventure,unity,游戏引擎,c#,游戏,Powered by 金山文档

同时设置Ruby的pivot,实现合理的显示顺序

unity入门项目Ruby‘s Adventure,unity,游戏引擎,c#,游戏,Powered by 金山文档
unity入门项目Ruby‘s Adventure,unity,游戏引擎,c#,游戏,Powered by 金山文档

之后把之前添加的物体都进行上述操作

五、物理系统

5.1精灵的物理系统

Ruby一直朝一个物体走时,应该要被挡住,而不是穿过去,为了实现这个效果,要为物体添加刚体和碰撞器

碰撞检测的其中一方必须要有刚体(最好是动的一方)

添加刚体,并将重力设为0,防止物体下坠,并冻结z轴的旋转,防止碰撞时Ruby旋转。

unity入门项目Ruby‘s Adventure,unity,游戏引擎,c#,游戏,Powered by 金山文档

碰撞检测的双方都要有碰撞器,给盒子和Ruby都添加加碰撞器,并修改到合适的大小,这样Ruby碰到盒子就会被挡住了,之后把其他物体也进这样的操作

unity入门项目Ruby‘s Adventure,unity,游戏引擎,c#,游戏,Powered by 金山文档

5.2瓦片的物理系统

单独的瓦片没有办法添加碰撞器

所以给Tilemap添加Tilemap Collider 2d和Composite Collider 2D

unity入门项目Ruby‘s Adventure,unity,游戏引擎,c#,游戏,Powered by 金山文档

并给需要碰撞器的瓦片(比如池塘)的Collider Type设为gird

unity入门项目Ruby‘s Adventure,unity,游戏引擎,c#,游戏,Powered by 金山文档
unity入门项目Ruby‘s Adventure,unity,游戏引擎,c#,游戏,Powered by 金山文档

六、添加生命值、道具

6.1添加生命值

Ruby是有生命值的,在触碰陷阱、敌人和草莓时生命值会改变,生命值小于等于0时会重生,所以需要添加相关代码。

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

public class RubyController : MonoBehaviour
{
    private Rigidbody2D rigidbody2d;
    //Ruby的移动速度
    public int speed = 5;
    //最大生命值
    public int maxHealth = 5;
    //Ruby的当前生命值
    private int currentHealth;
    //重生地点
    private Vector3 respawnPosition;
    //Ruby的无敌时间
    public float timeInvincible = 2.0f; //无敌时间常量
    private bool isInvincible;
    //计时器
    public float invincibleTimer;

    //外部可以访问Ruby的血量
    public int Health { get { return currentHealth; } }
    void Start()
    {
        rigidbody2d = GetComponent<Rigidbody2D>();
        //游戏开始时满血
        currentHealth = maxHealth;
        //重生地点为出生地
        respawnPosition = transform.position;
        //开始时无敌
        isInvincible = true;
    }

    // Update is called once per frame
    void Update()
    {
        //获取键盘的轴向输入
        float horizontal = Input.GetAxis("Horizontal");
        float vertical = Input.GetAxis("Vertical");
        //创建一个position记录移动后的位置
        Vector2 position = transform.position;
        //改变x,y轴上位置
        position.x = position.x + speed * horizontal * Time.deltaTime;
        position.y = position.y + speed * vertical * Time.deltaTime;
        //将主角的位置置为移动后的位置
        rigidbody2d.MovePosition(position);

        if (isInvincible)
        {
            invincibleTimer = invincibleTimer - Time.deltaTime;
            if (invincibleTimer <= 0)
            {
                //无敌时间结束,Ruby又可以受到伤害了
                isInvincible = false;
            }
        }
    }
    //改变血量的函数
    public void ChangeHealth(int amount)
    {
        if (amount < 0)
        {
            //如果是无敌状态,直接return
            if (isInvincible)
            {
                return;
            }
            //受到伤害
            isInvincible = true;
            invincibleTimer = timeInvincible;
        }
        currentHealth = Mathf.Clamp(currentHealth + amount, 0, maxHealth); //将血量currentHealth限定在0到maxHealth
        //Debug.Log("Ruby当前的生命值是:"+currentHealth + "/" + maxHealth);
        
        //血量小于等于0会重生
        if (currentHealth <= 0)
        {
            Respawn();
        }
    }
    //重生方法
    private void Respawn()
    {
        ChangeHealth(maxHealth);
     	//改变Ruby位置
        transform.position = respawnPosition;
    }
}

6.2制作血量回复道具

制作生命回复道具草莓,并添加脚本,以实现Ruby不是满血时回复一点生命值。

unity入门项目Ruby‘s Adventure,unity,游戏引擎,c#,游戏,Powered by 金山文档
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class HealthCollectible : MonoBehaviour
{
    // Start is called before the first frame update
    private void OnTriggerEnter2D(Collider2D collision)
    {
        //Debug.Log("与我们发生碰撞的是:" + collision);
        RubyController rubyController = collision.GetComponent<RubyController>();
        //接触到的物体有RubyController组件,即接触到的物体是Ruby
        if (rubyController != null)
        {
            if (rubyController.Health < rubyController.maxHealth)//Ruby不满血
            {
                //回复一点生命值
                rubyController.ChangeHealth(1);
                //将草莓销毁
                Destroy(gameObject);
            }
        }
    }
}

制作陷阱区域DamageZone,Ruby触碰到后生命值减1,并有一段无敌时间,防止一直扣血,无敌时间过后如果还在区域内,继续扣一点生命值。

unity入门项目Ruby‘s Adventure,unity,游戏引擎,c#,游戏,Powered by 金山文档
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class DamageZone : MonoBehaviour
{
    // Start is called before the first frame update
    private void OnTriggerStay2D(Collider2D collision)
    {
        RubyController rubyController = collision.GetComponent<RubyController>();
        if (rubyController != null)//接触到的物体有RubyController组件,即接触到的物体是Ruby
        {
            rubyController.ChangeHealth(-1);
        }
    }
}

七、添加敌人

添加一个敌人,并添加好刚体、碰撞器和脚本,编写脚本,使敌人自动来回移动,当敌人和Ruby相接触时,Ruby的生命值减少。

unity入门项目Ruby‘s Adventure,unity,游戏引擎,c#,游戏,Powered by 金山文档
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class EnemyController : MonoBehaviour
{
    public float speed = 3;
    private Rigidbody2D rigidbody2d;

    public bool vertical;
    //方向控制
    private int direction = 1;
    //改变移动方向的时间
    public float changeTime = 3;
    private float timer;

    void Start()
    {
        rigidbody2d = GetComponent<Rigidbody2D>();
    }
    // Update is called once per frame
    void Update()
    {
        //以下都是移动
        timer -= Time.deltaTime;
        //时间减到比0小时,改变移动方向
        if (timer < 0)
        {
            direction = -direction;
            //animator.SetFloat("MoveX", direction);
            timer = changeTime;
        }
        Vector2 position = rigidbody2d.position;
        if (vertical)
        {
            position.y = position.y + Time.deltaTime * speed * direction;
        }
        else
        {
            position.x = position.x + Time.deltaTime * speed * direction;
        }
        rigidbody2d.MovePosition(position);
    }
    //和Ruby接触时,Ruby生命值降低
    private void OnCollisionEnter2D(Collision2D collision)
    {
        RubyController rubyController = collision.gameObject.GetComponent<RubyController>();
        //判断接触到的是Ruby
        if (rubyController != null)
        {
            rubyController.ChangeHealth(-1);
        }
    }
}

八、动画系统

到现在为止,Ruby和敌人移动时只是一张图片在平移,为了播放对应的动画,需要使用Unity的动画系统。

8.1敌人的动画

创建一个动画控制器,添加到敌人上。

unity入门项目Ruby‘s Adventure,unity,游戏引擎,c#,游戏,Powered by 金山文档

创建好上下左右移动的动画

unity入门项目Ruby‘s Adventure,unity,游戏引擎,c#,游戏,Powered by 金山文档

制作好四个方向的动画之后,拖到动画控制器中,使用混合树来控制动画切换。

unity入门项目Ruby‘s Adventure,unity,游戏引擎,c#,游戏,Powered by 金山文档
unity入门项目Ruby‘s Adventure,unity,游戏引擎,c#,游戏,Powered by 金山文档
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class EnemyController : MonoBehaviour
{
    public float speed = 3;
    private Rigidbody2D rigidbody2d;

    private Animator animator;

    public bool vertical;
    //方向控制
    private int direction = 1;
    public float changeTime = 3;
    private float timer;


    void Start()
    {
        rigidbody2d = GetComponent<Rigidbody2D>();
        animator = GetComponent<Animator>();
    }

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

        //以下都是移动
        timer -= Time.deltaTime;
        if (timer < 0)
        {
            //改变移动方向
            direction = -direction;
            PlayMoveAnimation();
            //animator.SetFloat("MoveX", direction);
            timer = changeTime;
        }
        Vector2 position = rigidbody2d.position;
        if (vertical)
        {
            position.y = position.y + Time.deltaTime * speed * direction;
        }
        else
        {
            position.x = position.x + Time.deltaTime * speed * direction;
        }
        rigidbody2d.MovePosition(position);
    }
    //和Ruby接触时,Ruby生命值降低
    private void OnCollisionEnter2D(Collision2D collision)
    {
        RubyController rubyController = collision.gameObject.GetComponent<RubyController>();
        //判断接触到的是Ruby
        if (rubyController != null)
        {
            rubyController.ChangeHealth(-1);
        }
    }

    //控制移动动画的方法
    private void PlayMoveAnimation()
    {
        //改变参数,已实现动画的方向的变化
        if (vertical)
        {
            animator.SetFloat("MoveX", 0);
            animator.SetFloat("MoveY", direction);
        }
        else
        {
            animator.SetFloat("MoveX", direction);
            animator.SetFloat("MoveY", 0);
        }
    }
}

8.2Ruby的动画

用同样的方法制作Ruby的动画,官方的资源中已经制作好了Ruby的控制器,动画和参数都已经设置好了

unity入门项目Ruby‘s Adventure,unity,游戏引擎,c#,游戏,Powered by 金山文档
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class RubyController : MonoBehaviour
{
    private Rigidbody2D rigidbody2d;
    //Ruby的移动速度
    public int speed = 5;
    //最大生命值
    public int maxHealth = 5;
    //Ruby的当前生命值
    private int currentHealth;
    //重生地点
    private Vector3 respawnPosition;

    //Ruby的无敌时间
    public float timeInvincible = 2.0f; //无敌时间常量
    private bool isInvincible;
    //计时器
    public float invincibleTimer;

    //外部可以访问Ruby的血量
    public int Health { get { return currentHealth; } }

    private Animator animator;
    //创建向量,表示方向
    private Vector2 lookDirection = new Vector2(1, 0);

    public GameObject projectilePrefab;
    void Start()
    {
        rigidbody2d = GetComponent<Rigidbody2D>();
        //游戏开始时满血
        currentHealth = maxHealth;
        //重生地点为出生地
        respawnPosition = transform.position;
        //开始时无敌
        isInvincible = true;
        //获取动画控制器
        animator = GetComponent<Animator>();
    }

    // Update is called once per frame
    void Update()
    {
        //获取键盘的轴向输入
        float horizontal = Input.GetAxis("Horizontal");
        float vertical = Input.GetAxis("Vertical");
        Vector2 move = new Vector2(horizontal, vertical);
        if (!Mathf.Approximately(move.x, 0) || !Mathf.Approximately(move.y, 0))
        {
            lookDirection.Set(move.x, move.y); //lookDirection=move;
            lookDirection.Normalize();

        }
		//控制动画的方向
        animator.SetFloat("Look X", lookDirection.x);
        animator.SetFloat("Look Y", lookDirection.y);
        animator.SetFloat("Speed", move.magnitude);//move的模长


        //创建一个position记录移动后的位置
        Vector2 position = transform.position;
        //改变x,y轴上位置
        //position.x = position.x + speed * horizontal * Time.deltaTime;
        //position.y = position.y + speed * vertical * Time.deltaTime;
        position = position + speed * move * Time.deltaTime;
        //将主角的位置置为移动后的位置
        rigidbody2d.MovePosition(position);

        if (isInvincible)
        {
            invincibleTimer = invincibleTimer - Time.deltaTime;
            if (invincibleTimer <= 0)
            {
                isInvincible = false;
            }
        }
    }
    //改变血量的函数
    public void ChangeHealth(int amount)
    {
        if (amount < 0)
        {
            //如果是无敌状态,直接return
            if (isInvincible)
            {
                return;
            }
            //受到伤害
            isInvincible = true;
            invincibleTimer = timeInvincible;
        }
        currentHealth = Mathf.Clamp(currentHealth + amount, 0, maxHealth); //将血量currentHealth限定在0到maxHealth
                                                                           //Debug.Log("Ruby当前的生命值是:"+currentHealth + "/" + maxHealth);

        //血量小于等于0重生
        if (currentHealth <= 0)
        {
            Respawn();
        }
    }

    private void Respawn()
    {
        ChangeHealth(maxHealth);
        transform.position = respawnPosition;
    }
}

九、发射齿轮

Ruby可以发射齿轮,击中物体会消失,如果击中的是敌人,敌人会被修好。另外,如果没有击中物体,也要让齿轮飞行一段距离后消失,否则齿轮会越来越多,消耗资源

9.1齿轮的开发

为了能够发射很多子弹,可以让Ruby发射齿轮时在Ruby面前生成一个齿轮,给它一个向前的力,如果碰到物体或飞行了一定的时间后就消失。

。首先创建一个子弹,添加刚体、碰撞器和脚本,编写脚本

unity入门项目Ruby‘s Adventure,unity,游戏引擎,c#,游戏,Powered by 金山文档
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Projectile : MonoBehaviour
{
    // Start is called before the first frame update
    private Rigidbody2D rigidbody2d;
    void Awake() //在实例化之前运行 用start会报错 原因:在主角中实例化后获取脚本,直接跑方法,而不运行start
    {
        rigidbody2d = GetComponent<Rigidbody2D>();
    }
    private void Update()
    {
        if (transform.position.magnitude > 20)
        {
            Destroy(gameObject);
        }
    }
    public void Launch(Vector2 direction, float force)
    {
        rigidbody2d.AddForce(direction * force);
    }
    private void OnCollisionEnter2D(Collision2D collision)
    {
        //Debug.Log("当前触碰到的物体是:" + collision.gameObject);
        Destroy(gameObject);
    }
}

RubyController也要修改,玩家按H时发射齿轮,并播放Hit动画。

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

public class RubyController : MonoBehaviour
{
    private Rigidbody2D rigidbody2d;
    //Ruby的移动速度
    public int speed = 5;
    //最大生命值
    public int maxHealth = 5;
    //Ruby的当前生命值
    private int currentHealth;
    //重生地点
    private Vector3 respawnPosition;

    //Ruby的无敌时间
    public float timeInvincible = 2.0f; //无敌时间常量
    private bool isInvincible;
    //计时器
    public float invincibleTimer;

    //外部可以访问Ruby的血量
    public int Health { get { return currentHealth; } }

    private Animator animator;
    //创建向量,表示方向
    private Vector2 lookDirection = new Vector2(1, 0);

    public GameObject projectilePrefab;
    void Start()
    {
        rigidbody2d = GetComponent<Rigidbody2D>();
        //游戏开始时满血
        currentHealth = maxHealth;
        //重生地点为出生地
        respawnPosition = transform.position;
        //开始时无敌
        isInvincible = true;
        //获取动画控制器
        animator = GetComponent<Animator>();
    }

    // Update is called once per frame
    void Update()
    {
        //获取键盘的轴向输入
        float horizontal = Input.GetAxis("Horizontal");
        float vertical = Input.GetAxis("Vertical");
        Vector2 move = new Vector2(horizontal, vertical);
        if (!Mathf.Approximately(move.x, 0) || !Mathf.Approximately(move.y, 0))
        {
            lookDirection.Set(move.x, move.y); //lookDirection=move;
            lookDirection.Normalize();

        }

        animator.SetFloat("Look X", lookDirection.x);
        animator.SetFloat("Look Y", lookDirection.y);
        animator.SetFloat("Speed", move.magnitude);//move的模长


        //创建一个position记录移动后的位置
        Vector2 position = transform.position;
        //改变x,y轴上位置
        //position.x = position.x + speed * horizontal * Time.deltaTime;
        //position.y = position.y + speed * vertical * Time.deltaTime;
        position = position + speed * move * Time.deltaTime;
        //将主角的位置置为移动后的位置
        rigidbody2d.MovePosition(position);

        if (isInvincible)
        {
            invincibleTimer = invincibleTimer - Time.deltaTime;
            if (invincibleTimer <= 0)
            {
                isInvincible = false;
            }
        }
        //按H发射齿轮
        if (Input.GetKeyDown(KeyCode.H))
        {
            Launch();
        }
    }
    //改变血量的函数
    public void ChangeHealth(int amount)
    {
        if (amount < 0)
        {
            //如果是无敌状态,直接return
            if (isInvincible)
            {
                return;
            }
            //受到伤害
            isInvincible = true;
            invincibleTimer = timeInvincible;
        }
        currentHealth = Mathf.Clamp(currentHealth + amount, 0, maxHealth); //将血量currentHealth限定在0到maxHealth
                                                                           //Debug.Log("Ruby当前的生命值是:"+currentHealth + "/" + maxHealth);

        if (currentHealth <= 0)
        {
            Respawn();
        }
    }

    private void Launch()
    {

        GameObject projectileObject = Instantiate(projectilePrefab, rigidbody2d.position+Vector2.up*0.5f, Quaternion.identity);
        Projectile projectile= projectileObject.GetComponent<Projectile>();
        projectile.Launch(lookDirection,300);
        animator.SetTrigger("Launch");
    }

    private void Respawn()
    {
        ChangeHealth(maxHealth);
        transform.position = respawnPosition;
    }
}

当齿轮创建出来时,检测到Ruby,所以会立刻消失,为了让齿轮和Ruby不发生碰撞建检测,需要把他们放在两个不同的层级,并让这两个层级不发生碰撞检测

unity入门项目Ruby‘s Adventure,unity,游戏引擎,c#,游戏,Powered by 金山文档

这样就可以正常发射齿轮了

unity入门项目Ruby‘s Adventure,unity,游戏引擎,c#,游戏,Powered by 金山文档

9.2敌人被击中的效果

敌人被击中时,会被修复,不再移动和造成伤害

需要修改敌人和齿轮的脚本

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

public class EnemyController : MonoBehaviour
{
    public float speed = 3;
    private Rigidbody2D rigidbody2d;

    private Animator animator;

    public bool vertical;
    //方向控制
    private int direction = 1;
    public float changeTime = 3;
    private float timer;

    //判断当前机器人是否故障
    private bool broken;

    void Start()
    {
        rigidbody2d = GetComponent<Rigidbody2D>();
        animator = GetComponent<Animator>();
        //开始时机器人是损坏的
        broken = true;
    }

    // Update is called once per frame
    void Update()
    {
        if (!broken)
        {
            //如果修好,不移动
            return;
        }
        //以下都是移动
        timer -= Time.deltaTime;
        if (timer < 0)
        {
            //改变移动方向
            direction = -direction;
            PlayMoveAnimation();
            //animator.SetFloat("MoveX", direction);
            timer = changeTime;
        }
        Vector2 position = rigidbody2d.position;
        if (vertical)
        {
            position.y = position.y + Time.deltaTime * speed * direction;
        }
        else
        {
            position.x = position.x + Time.deltaTime * speed * direction;
        }
        rigidbody2d.MovePosition(position);
    }
    private void OnCollisionEnter2D(Collision2D collision)
    {
        RubyController rubyController = collision.gameObject.GetComponent<RubyController>();
        if (rubyController != null)
        {
            rubyController.ChangeHealth(-1);
        }
    }

    //控制移动动画的方法
    private void PlayMoveAnimation()
    {
        if (vertical)
        {
            animator.SetFloat("MoveX", 0);
            animator.SetFloat("MoveY", direction);
        }
        else
        {
            animator.SetFloat("MoveX", direction);
            animator.SetFloat("MoveY", 0);
        }
    }
    //修复方法
    public void Fix()
    {
        broken = false;
        rigidbody2d.simulated = false;
        //播放修复好的动画
        animator.SetTrigger("Fixed");
    }
}

齿轮在检测到碰撞到的物体是敌人后,会调用敌人的Fix()方法,实现机器人的修复

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Projectile : MonoBehaviour
{
    // Start is called before the first frame update
    private Rigidbody2D rigidbody2d;
    void Awake() //在实例化之前运行 用start会报错 原因:在主角中实例化后获取脚本,直接跑方法,而不运行start
    {
        rigidbody2d = GetComponent<Rigidbody2D>();
    }
    private void Update()
    {
        if (transform.position.magnitude > 20)
        {
            Destroy(gameObject);
        }
    }
    public void Launch(Vector2 direction, float force)
    {
        rigidbody2d.AddForce(direction * force);
    }
    private void OnCollisionEnter2D(Collision2D collision)
    {
        //Debug.Log("当前触碰到的物体是:" + collision.gameObject);
        EnemyController enemyController = collision.gameObject.GetComponent<EnemyController>();
        if (enemyController != null)
        {
            enemyController.Fix();
        }
        Destroy(gameObject);
    }
}

十.镜头跟随

为了让Ruby移动时镜头能够跟随Ruby,需要添加虚拟相相机

10.1添加虚拟相机

在Package Manager中导入包

unity入门项目Ruby‘s Adventure,unity,游戏引擎,c#,游戏,Powered by 金山文档

创建一个虚拟相机

unity入门项目Ruby‘s Adventure,unity,游戏引擎,c#,游戏,Powered by 金山文档

让虚拟相机跟随Ruby,并添加限制器,防止视角跑出地图外

unity入门项目Ruby‘s Adventure,unity,游戏引擎,c#,游戏,Powered by 金山文档

十一.完善地图并制作地图边界

添加更多物体,使地图更加丰富。并制作好边界,使相机的范围不会超过限制范围

unity入门项目Ruby‘s Adventure,unity,游戏引擎,c#,游戏,Powered by 金山文档

十二、粒子系统

12.1烟雾特效

为了让机器人损坏时有冒烟的特效,添加一个粒子系统

unity入门项目Ruby‘s Adventure,unity,游戏引擎,c#,游戏,Powered by 金山文档

并调整参数和图片,已实现烟雾效果

unity入门项目Ruby‘s Adventure,unity,游戏引擎,c#,游戏,Powered by 金山文档

修改机器人的脚本,时机器人被修复时不播放烟雾效果

//烟雾系统
public ParticleSystem smokeEffect;

//....重复代码省略

    public void Fix()
    {
        broken = false;
        rigidbody2d.simulated = false;
        animator.SetTrigger("Fixed");
        //烟雾停止
        smokeEffect.Stop();
    }

12.2击打特效

制作击打特效,在齿轮碰撞物体时产生

unity入门项目Ruby‘s Adventure,unity,游戏引擎,c#,游戏,Powered by 金山文档
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Projectile : MonoBehaviour
{
    // Start is called before the first frame update
    private Rigidbody2D rigidbody2d;
    //爆炸特效
    public GameObject effectParticle;
    void Awake() //在实例化之前运行 用start会报错 原因:在主角中实例化后获取脚本,直接跑方法,而不运行start
    {
        rigidbody2d = GetComponent<Rigidbody2D>();
    }
    private void Update()
    {
        if (transform.position.magnitude > 20)
        {
            Destroy(gameObject);
        }
    }
    public void Launch(Vector2 direction, float force)
    {
        rigidbody2d.AddForce(direction * force);
    }
    private void OnCollisionEnter2D(Collision2D collision)
    {
        //Debug.Log("当前触碰到的物体是:" + collision.gameObject);
        //原地生成爆炸特效
        EnemyController enemyController = collision.gameObject.GetComponent<EnemyController>();
        if (enemyController != null)
        {
            enemyController.Fix();
        }
        Destroy(gameObject);
    }
}

12.3回血特效

Ruby拾取草莓时生成回血特效

unity入门项目Ruby‘s Adventure,unity,游戏引擎,c#,游戏,Powered by 金山文档
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class HealthCollectible : MonoBehaviour
{
    //回复特效
    public GameObject effectParticle;
    // Start is called before the first frame update
    private void OnTriggerEnter2D(Collider2D collision)
    {
        //Debug.Log("与我们发生碰撞的是:" + collision);
        RubyController rubyController = collision.GetComponent<RubyController>();
        //接触到的物体有RubyController组件,即接触到的物体是Ruby
        if (rubyController != null)
        {
            if (rubyController.Health < rubyController.maxHealth)//Ruby不满血
            {
                //原地生成回复特效
                Instantiate(effectParticle, transform.position, Quaternion.identity);
                rubyController.ChangeHealth(1);
                Destroy(gameObject);
            }
        }

    }
}

十三.UGUI

13.1血条制作

为了显示Ruby的血量,创建一个Canvas,在里面制作出血条,放在屏幕左上角

unity入门项目Ruby‘s Adventure,unity,游戏引擎,c#,游戏,Powered by 金山文档

用血量图片的伸缩表示血量的多少,需要用脚本控制血条变化

unity入门项目Ruby‘s Adventure,unity,游戏引擎,c#,游戏,Powered by 金山文档
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class UIHealthBar : MonoBehaviour
{
    public Image mask;
    float originalSize;
    public static UIHealthBar instance { get; private set; }
    public int fixedNum=0;
    // Start is called before the first frame update
    public void Awake()
    {
        instance = this;
    }
    void Start()
    {
        originalSize = mask.rectTransform.rect.width;
    }
    // Update is called once per frame
    void Update()
    {
        
    }
    public void SetValue(float fillPercent)
    {
        mask.rectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, originalSize * fillPercent);
    }
}

血条会随血量变化而变化

unity入门项目Ruby‘s Adventure,unity,游戏引擎,c#,游戏,Powered by 金山文档

十四、制作NPC

游戏中需要NPC,Ruby和NPC对话后可以发射子弹,并且当Ruby修好所有机器人后NPC和Ruby的对话会改变

14.1NPC创建

拖入NPC的图片,并添加动画控制器,制作动画,添加碰撞器

unity入门项目Ruby‘s Adventure,unity,游戏引擎,c#,游戏,Powered by 金山文档

14.2与NPC对话

在NPC面前创建对话框

unity入门项目Ruby‘s Adventure,unity,游戏引擎,c#,游戏,Powered by 金山文档

当Ruby在NPC面前按下T时,对话框出现

先创建NPC的脚本

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

public class NPCDialog : MonoBehaviour
{
    public GameObject dialogBox;
    public float displayTime=3.0f;
    private float timerDisplay=-1;
    public Text dialogText;
    public AudioSource audioSource;
    public AudioClip winSound;
    public bool hasPlayed=false;
    // Start is called before the first frame update
    void Start()
    {
        timerDisplay = displayTime;
        dialogBox.SetActive(false);
    }

    // Update is called once per frame
    void Update()
    {
        if (timerDisplay >= 0)
        {
            timerDisplay = timerDisplay - Time.deltaTime;
        }
        else
        {
            dialogBox.SetActive(false);
        }
    }
    public void DisPlayDialog()
    {
        timerDisplay = displayTime;
        dialogBox.SetActive(true);
    }
}

为了检测Ruby是否在NPC面前,使用射线检测,检测到NPC时,显示对话框

在RubyController中的Update中添加if语句,如果检测到的物体是在NPC的layer中,调用NPC的脚本显示对话框,因此需要把NPC放在“NPC”的layer中

    if(Input.GetKeyDown(KeyCode.T))
    {
		//射线检测到NPC
        RaycastHit2D hit = Physics2D.Raycast(rigidbody2d.position + 				   Vector2.up*0.2f,lookDirection,1.5f,LayerMask.GetMask("NPC"));
        if(hit.collider!=null)
        {
            NPCDialog npcDialog = hit.collider.GetComponent<NPCDialog>();
            if(npcDialog!=null)
            {
                npcDialog.DisPlayDialog();
            }
        }
    }

十五、添加音乐和音效

15.1背景音乐

添加一个空物体,添加Audio Source并添加背景音乐,勾选loop循环播放

unity入门项目Ruby‘s Adventure,unity,游戏引擎,c#,游戏,Powered by 金山文档

15.2添加音效

给Ruby挂载上音效,实现受伤、发射、走路的音效

unity入门项目Ruby‘s Adventure,unity,游戏引擎,c#,游戏,Powered by 金山文档
using System.Collections;
using System.Collections.Generic;
using UnityEngine; 

public class RubyController : MonoBehaviour
{
    private Rigidbody2D rigidbody2d;
    public int speed = 10;//Ruby的速度
    public int maxHealth = 5;//最大生命值
    private int currentHealth;//Ruby的当前生命值

    //Ruby的无敌时间
    public float timeInvincible = 2.0f; //无敌时间常量
    private bool isInvincible;
    public float invincibleTimer;//计时器

    private Vector2 lookDirection = new Vector2(1, 0);
    private Animator animator;

    public GameObject projectilePrefab;

    //音频资源
    public AudioSource audioSource;
    public AudioSource walkAudioSource;
    public AudioClip playerHit;
    public AudioClip attackSoundClip;
    public AudioClip walkSound;
    public int Health { get { return currentHealth; }} //get只读 set{health=value;} 写

    private Vector3 respawnPosition;

    // Start is called before the first frame update
    void Start()
    {
        rigidbody2d = GetComponent<Rigidbody2D>();
        currentHealth = maxHealth;

        animator = GetComponent<Animator>();
        isInvincible = true;
        //int a = GetRubyHealthValue();
        //Debug.Log("Ruby当前的血量是:" + a);
        //SpriteRenderer dog = GetComponent<SpriteRenderer>();

        audioSource = GetComponent<AudioSource>();
        respawnPosition = transform.position;
    }

    // Update is called once per frame
    void Update()
    {
        float h=Input.GetAxis("Horizontal");
        float v = Input.GetAxis("Vertical");

        Vector2 move = new Vector2(h, v);
        if (!Mathf.Approximately(move.x, 0) || !Mathf.Approximately(move.y, 0))
        {
            lookDirection.Set(move.x, move.y); //lookDirection=move;
            lookDirection.Normalize();
            //如果走路音效没有在播放,播放走路音效
            if(!walkAudioSource.isPlaying)
            {
                walkAudioSource.Play();
                walkAudioSource.clip = walkSound;
            }
        }
        else
        {
            //已经在播放则不播放
            walkAudioSource.Stop();
        }
        //控制动画方向
        animator.SetFloat("Look X",lookDirection.x);
        animator.SetFloat("Look Y",lookDirection.y);
        animator.SetFloat("Speed", move.magnitude);//move的模长

        Vector2 position = transform.position;
        //position.x = position.x + speed*h*Time.deltaTime;
        //position.y = position.y + speed*v*Time.deltaTime;
        position = position + speed * move * Time.deltaTime;
        rigidbody2d.MovePosition(position);

        if(isInvincible)
        {
            invincibleTimer = invincibleTimer - Time.deltaTime;
            if(invincibleTimer<=0)
            {
                isInvincible = false;
            }
        }
        if(Input.GetKeyDown(KeyCode.H))
        {
            Launch();
        }
        if(Input.GetKeyDown(KeyCode.T))
        {

            RaycastHit2D hit = Physics2D.Raycast(rigidbody2d.position + Vector2.up*0.2f,lookDirection,1.5f,LayerMask.GetMask("NPC"));
            if(hit.collider!=null)
            {
                NPCDialog npcDialog = hit.collider.GetComponent<NPCDialog>();
                if(npcDialog!=null)
                {
                    npcDialog.DisPlayDialog();
                }
            }
        }

    }
    public void ChangeHealth(int amount)
    {
        if(amount<0)
        {
            if(isInvincible)
            {
                return;
            }
            animator.SetTrigger("Hit");
            isInvincible = true;
            //播放受伤音效
            PlaySound(playerHit);
            invincibleTimer = timeInvincible;
        }
        currentHealth = Mathf.Clamp(currentHealth + amount, 0, maxHealth); //将血量currentHealth限定在0到maxHealth
        //Debug.Log("Ruby当前的生命值是:"+currentHealth + "/" + maxHealth);
        UIHealthBar.instance.SetValue(currentHealth / (float)maxHealth);
        if(currentHealth<=0)
        {
                Respawn();
        }
        
    }
    private void Launch()
    {
        GameObject projectileObject = Instantiate(projectilePrefab, rigidbody2d.position+Vector2.up*0.5f, Quaternion.identity);
        Projectile projectile= projectileObject.GetComponent<Projectile>();
        projectile.Launch(lookDirection,300);
        animator.SetTrigger("Launch");
        //发射时播放发射音频
        PlaySound(attackSoundClip);
      
    }

    //播放音效的方法
    public void PlaySound(AudioClip audioClip)
    {
        audioSource.PlayOneShot(audioClip);
    }

    private void Respawn()
    {
        ChangeHealth(maxHealth);
        transform.position = respawnPosition;
    }
}

Ruby拾取草莓回血后,也会播放音效

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

public class HealthCollectible : MonoBehaviour
{
    public AudioClip audioClip;
    //回复特效
    public GameObject effectParticle;
    // Start is called before the first frame update
    private void OnTriggerEnter2D(Collider2D collision)
    {
        //Debug.Log("与我们发生碰撞的是:" + collision);
        RubyController rubyController = collision.GetComponent<RubyController>();
        if(rubyController!=null)//接触到的物体有RubyController组件,即接触到的物体是Ruby
        {
            if (rubyController.Health<rubyController.maxHealth)//Ruby不满血
            {
                //原地生成一个回复特效
                Instantiate(effectParticle, transform.position, Quaternion.identity);
                rubyController.ChangeHealth(1);
                //播放回血音效
                rubyController.PlaySound(audioClip);
                Destroy(gameObject);
            }
        }
    }
}

机器人走动时、被修好时也有音效

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

public class EnemyController : MonoBehaviour
{
    public float speed=3;
    private Rigidbody2D rigidbody2d;

    public bool vertical;
    //方向控制
    private int direction = 1;
    public float changeTime = 3;
    private float timer;

    private Animator animator;
    //当前机器人是否故障
    private bool broken;

    public ParticleSystem smokeEffect;
    // Start is called before the first frame update

    //音频资源
    private AudioSource audioSource;
    public AudioClip fixSound;
    public AudioClip[] hitSounds;

    public GameObject hitEffectParticle;
    void Start()
    {
        rigidbody2d = GetComponent<Rigidbody2D>();
        timer = changeTime;
        animator = GetComponent<Animator>();
        //animator.SetFloat("MoveX", direction);
        //animator.SetBool("Vertical", vertical);
        PlayMoveAnimation();
        broken = true;
        audioSource = GetComponent<AudioSource>();
    }

    // Update is called once per frame
    void Update()
    {
        if(!broken)
        {
            //如果修好,不移动
            return;
        }
        //以下都是移动
        timer -= Time.deltaTime;
        if(timer<0)
        {
            direction = -direction;
            //animator.SetFloat("MoveX", direction);
            PlayMoveAnimation();

            timer = changeTime;
        }
        Vector2 position = rigidbody2d.position;
        if(vertical)
        {
            position.y = position.y + Time.deltaTime * speed*direction;
        }
        else
        {
            position.x = position.x + Time.deltaTime * speed*direction;
        }
        rigidbody2d.MovePosition(position);
    }
    private void OnCollisionEnter2D(Collision2D collision)
    {
        RubyController rubyController = collision.gameObject.GetComponent<RubyController>();
        if(rubyController!=null)
        {
            rubyController.ChangeHealth(-1);
        }
    }

    //控制移动动画的方法
    private void PlayMoveAnimation()
    {
        if (vertical)
        {
            animator.SetFloat("MoveX", 0);
            animator.SetFloat("MoveY", direction);
        }
        else
        {
            animator.SetFloat("MoveX", direction);
            animator.SetFloat("MoveY", 0);
        }
    }

    public void Fix()
    {
        Instantiate(hitEffectParticle, transform.position, Quaternion.identity);
        broken = false;
        rigidbody2d.simulated = false;
        animator.SetTrigger("Fixed");
        smokeEffect.Stop();

        int randomNum = Random.Range(0, 2);
        //被修好时停止走路音频
        audioSource.Stop();
        audioSource.volume = 0.5f;
        //播放击中音效
        audioSource.PlayOneShot(hitSounds[randomNum]);
        Invoke("PlayFixSound",0.1f);

    }

    //被修好音效的方法
    private void PlayFixSound()
    {
        audioSource.PlayOneShot(fixSound);
    }

}

十六、任务系统

游戏中Ruby并不是一开始就可以发射齿轮的,只有在接收了NPC的任务之后才能解锁发射齿轮。当Ruby修复好了所有机器人之后,任务完成,可以向NPC提交任务。

16.1接受任务

为了判断是都接受任务,需要一个全局变量hasTask,我们放在UIHealthBar中

//是否有任务
    public bool hasTask;

在NPCDialog中的DisPlayDialog()中添加语句,让Ruby在接受任务时将该值置为true

    public void DisPlayDialog()
    {
        timerDisplay = displayTime;
        dialogBox.SetActive(true);
        //接到任务
        UIHealthBar.instance.hasTask = true;
    }

修改Ruby的Lauch()方法

    private void Launch()
    {
		//没有任务直接return,无法发射齿轮
        if (UIHealthBar.instance.hasTask ==false)
        {
            return;
        }
        GameObject projectileObject = Instantiate(projectilePrefab, rigidbody2d.position+Vector2.up*0.5f, Quaternion.identity);
        Projectile projectile= projectileObject.GetComponent<Projectile>();
        projectile.Launch(lookDirection,300);
        animator.SetTrigger("Launch");
        PlaySound(attackSoundClip);
    }

这样只有在接收到任务时才能发射齿轮了。

16.2完成任务

为了判断任务是否完成,需要添加一个全局变量,fixedNum,每修好一个机器人,fixedNum就加一,当修好所有机器人后,任务就算完成了,对话框会修改,并且播放胜利音效

    //用修好的数量判断任务是否完成
    public int fixedNum=0;

敌人脚本的Fix()方法,当一个机器人执行Fix()方法后,就代表有一个机器人被修好,所以fixedNum加1

public void Fix()
{
    //修好的机器人数量加一
    UIHealthBar.instance.fixedNum++;
    Instantiate(hitEffectParticle, transform.position, Quaternion.identity);
    broken = false;
    rigidbody2d.simulated = false;
    animator.SetTrigger("Fixed");
    smokeEffect.Stop();

    int randomNum = Random.Range(0, 2);
    audioSource.Stop();
    audioSource.volume = 0.5f;
    audioSource.PlayOneShot(hitSounds[randomNum]);
    Invoke("PlayFixSound",0.1f);

}

NPCDialog的DisPlayDialog()方法

public void DisPlayDialog()
{
    timerDisplay = displayTime;
    dialogBox.SetActive(true);
    UIHealthBar.instance.hasTask = true;
    //所有机器人都被修好,我的场景中添加了5个机器人,所有fixedNum大鱼大于等于5时任务就完成了
    if(UIHealthBar.instance.fixedNum>=5)
    {
        //完成任务,修改对话框
        dialogText.text = "哦,谢谢你Ruby,你太棒了!";
        if(hasPlayed==false)
        {
            //播放胜利音效
            audioSource.PlayOneShot(winSound);
            hasPlayed = true;
        }  
    }
}

十七、游戏打包

游戏基本制作完成后,打包

设置好游戏图标等信息

unity入门项目Ruby‘s Adventure,unity,游戏引擎,c#,游戏,Powered by 金山文档

然后在Build Settings中Build

unity入门项目Ruby‘s Adventure,unity,游戏引擎,c#,游戏,Powered by 金山文档

找到exe文件运行,就可以直接游玩游戏了。文章来源地址https://www.toymoban.com/news/detail-717270.html

到了这里,关于unity入门项目Ruby‘s Adventure的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 使用团结引擎开发Unity 3D射击游戏

           本案例是初级案例,意在引导想使用unity的初级开发者能较快的入门,体验unity开发的方便性和简易性能。       本次我们将使用团结引擎进行开发,帮助想体验团结引擎的入门开发者进行较快的环境熟悉。      本游戏是一个俯视角度的射击游戏。主角始终位于屏幕

    2024年01月19日
    浏览(52)
  • Unity、UE、Cocos游戏开发引擎的区别

    Unity、Unreal Engine(UE)和Cocos引擎是三个常用的游戏开发引擎,它们在功能和特性上有一些区别。以下是它们之间的主要区别: 编程语言:Unity使用C#作为主要的编程语言,开发者可以使用C#脚本进行游戏逻辑编写。Unreal Engine主要使用C++作为编程语言,但也支持蓝图系统,允许

    2024年02月22日
    浏览(47)
  • 30分钟了解所有引擎组件,132个Unity 游戏引擎组件速通!【收藏 == 学会】

    🎬 博客主页:https://xiaoy.blog.csdn.net 🎥 本文由 呆呆敲代码的小Y 原创,首发于 CSDN 🙉 🎄 学习专栏推荐:Unity系统学习专栏 🌲 游戏制作专栏推荐:游戏制作 🌲Unity实战100例专栏推荐:Unity 实战100例 教程 🏅 欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请指正! 📆 未来很长

    2024年02月11日
    浏览(52)
  • python游戏开发入门经典教程,python游戏开发引擎

    大家好,给大家分享一下python游戏开发入门经典教程,很多人还不知道这一点。下面详细解释一下。现在让我们来看看! 消消乐小游戏相信大家都玩过,大人小孩都喜欢玩的一款小游戏,那么基于程序是如何实现的呢?今天带大家,用python+pygame来实现一下这个花里胡哨的消

    2024年02月02日
    浏览(36)
  • Unity vs Godot :哪个游戏引擎更适合你?

    游戏引擎的选择对开发过程和最终产品质量有着重大影响。近年来,Godot和Unity这两款引擎受到广泛关注。本文将从多个维度对两者进行比较,以期为开发者提供正确的选择建议。 Godot和Unity都有各自的优势,没有绝对的好坏之分。Godot开源免费,上手简单,更适合2D和小型游戏

    2024年01月23日
    浏览(74)
  • Hazel游戏引擎(004)项目设置

    本人菜鸟,文中若有代码、术语等错误,欢迎指正 我写的项目地址:https://github.com/liujianjie/GameEngineLightWeight(中文的注释适合中国人的你) 此节目的 新建好Hazel和Sandbox项目,Hazel项目生成为dll,Sandbox项目生成为exe,运行此exe通过动态链接Hazel的dll,可以调用dll定义的函数并

    2024年01月16日
    浏览(49)
  • GAMES104-现代游戏引擎:从入门到实践 - 物理引擎课程笔记汇总

    GAMES104-现代游戏引擎:从入门到实践_课程视频_bilibili GAMES104官方账号 - 知乎 课程主页 课程小引擎Piccolo 课件: GAMES104_Lecture10_Physics System_Basic Concepts.pdf GAMES104_Lecture11_Physics System_Applications.pdf 物理引擎的用途: 碰撞检测 解决碰撞、其它约束限制 更新所有物体的世界坐标(w

    2024年01月17日
    浏览(38)
  • Unity Physics2D 2d物理引擎游戏 笔记

    2d 材质 里面可以设置 摩擦力 和 弹力 Simulated:是否在当前的物理环境中模拟,取消勾选该框类似于Disable Rigidbody,但使用这个参数更加高效,因为Disable会销毁内部产生的GameObject,而取消勾选Simulated只是禁用。 Kinematic 动力学刚体 动力学刚体不受重力和力的影响,而受用户的

    2023年04月24日
    浏览(102)
  • Unity和UE4两大游戏引擎,你该如何选择?

    目录 游戏引擎 2 —— 难易区别 编程语言 3 —— 游戏产品 UE4制作的游戏产品  Unity制作的游戏产品  产品类型 5 —— 资源商店 6 —— 人才需求 平均薪资 总结      Unity和UE4都是游戏引擎,所谓游戏引擎就是集成了复杂功能的游戏开发软件,他们帮我们实现了复杂的底层逻

    2023年04月08日
    浏览(53)
  • GODOT游戏引擎简介,包含与unity性能对比测试,以及选型建议

    GODOT,是一个免费开源的3D引擎。本文以unity作对比,简述两者区别和选型建议。由于是很久以前写的ppt,技术原因视频和部分章节丢失了。建议当做业务参考。 GODOT目前为止遇到3个比较重大的机遇,第一个是oprea的合作奖,第二个是用支持c#换来的微软的投资,第三个是虚幻

    2024年02月14日
    浏览(48)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包