0
点赞
收藏
分享

微信扫一扫

《Unity3D脚本编程与游戏开发》学习Day one

_刘彦辉 2022-09-25 阅读 180

Unity学习第一日

前言

 Unity 是实时3D互动内容创作和运营平台。
 使用Unity前我们需要先了解这个游戏引擎
Unity官网

Unity介绍

  • 使用Unity开发的软件:
    原神
    王者荣耀
    明日方舟
    使命召唤手游
    炉石传说

  • 百度百科

  • Unity 用户手册

游戏开发技术

  • 游戏设计 (游戏的灵魂)
  • 美术制作 (游戏的外表)
  • 技术实现 (游戏的骨骼和血肉)

技术实现与游戏设计

游戏技术游戏设计互相促进:技术设计带来可能性的空间,设计指导者技术的发展方向。

第一章 Unity脚本概览

本章主在让读者体会脚本编程的思路整体方法

1.1 控制物体的移动

本节将详细讲解创建脚本、改变物体位置、处理用户输入等基本操作

1.1.1 新建脚本并挂载

  • 脚本的创建
    • 方法一:
      在Project(工程)窗口某个文件夹中,单机鼠标右键选择:Create->C# Script选项。
    • 方法二:
      先新建一个球体,即在Hierarchy窗口,单机鼠标右键选择:3D object->Sphere选项。
      然后选中球体,在Insperctor(检视)窗口单击:Add Component(添加组件)按钮,在菜单中选择:New script (新建脚本)选项,输入脚本文件名单击:Create and Add(创建并添加)。
  • 脚本的挂载
    • 方法一:
      拖拽脚本到场景中的球体上。
    • 方法二:
      拖拽脚本到Inspector窗口中项目的最后面。(推荐使用)
  • 脚本组件的删除
     在组件名称上单击鼠标右键,选择:Remove Component(删除组件)。
  • 注意事项
     Unity 规定:能够挂载到物体上的脚本文件必须是“脚本组件”,脚本组件要继承自MonoBehaviour,且脚本代码中的class名称必须与文件名一致。(因此在修改脚本文件名时,必须同时修改class名称)。
     Unity 支持一个物体挂载多个同样的脚本组件。

1.1.2 Start 和 Updata 事件

  • 双击脚本文件打开脚本,目前脚本中的内容是自动生成的,包括:
    using UnityEngine(使用UnityEngine这个命名空间)
    Start(函数)
    Update(函数)
  • Start和Update函数
    Start函数在游戏开始运行依次,适合进行组件初始化。
    Update函数每帧都会执行,根据系统资源情况,帧率可能实时变化,因此Update的执行频率(每秒执行次数)是变化的。
    Start和Update又被称为“事件”,因为它们分别是在“组件开始运行”和“更新该组件”这两个事件发生时被调用的。
  • Debug.Log函数
    作用:向Console(控制台)窗口输出一串信息。
    用处:写代码、调试代码,是最简单、最可靠的一种调试手段。
  • Time类
    Time.time:显示游戏运行时间。
    Time.deltaTime:表示从上一帧到当前帧时间,时间增量。
    Time.timeScale函数(时间缩放:默认值为1,游戏的暂停为0,游戏的快进可为2)。
    Time类详解

1.1.3 修改物体位置

  • 在Unity 中,修改物体位置实际上就是修改Transform(变换)组件的数据
  • Inspector窗口展示了组件的位置(Position)、旋转(Rotation)、缩放(Scale)参数
  • 在界面上可以修改的内容一定可以在脚本中修改,但在脚本中修改的内容不一定能在节目中修改,因为脚本的功能比界面展示的功能要多得多
  • 修改Transform组件中的Position的两种常用方法
    • 使用Translate()函数。
      即:tansform.Translate(x,y,z)。其中x、y、z为float类型量,若为常量要加上后缀f表示float类型,否则C# 认为其为double类型。如 3.12为double类型,3.12f为float类型。 (代码写于脚本函数中)
    • 直接指定新的位置
      即:tansform.position = new Vector3(x,y,z)。
    • 上述两种方法的区别:Translate函数默认为局部坐标系,而修改position的方法是世界坐标系。
  • 类型转换
    int可以隐式转换为float,所以x、y、z如果没有小数位可以不加f后缀,但int转float精度会降低(题外话)。
    类型转换
  • 位置移动代码
    void Update(){
    	tansform.Translate(0,0,0.1f);
    	tansform.position += new Vector3(0,0,0.1f);
    }
    
  • 游戏设计注意事项
     由于系统繁忙时无法保证稳定的帧率,因此对于上述代码,会导致小球的移动速度和帧率成正比。
    是“每帧移动距离相同”还是“每秒移动距离相同”呢?这需要根据游戏设计来确定,大多情况下是”每秒移动距离相同“,因此移动的距离应该针对帧率去确定,”每秒移动距离相同“的代码如下。
    void Update(){
    	tansform.Translate(0,0,5*Time.deltaTime);
    	tansform.position += new Vector3(0,0,5*Time.deltaTime);
    }
    
     代码中5表示速度,上述代码的改进原理基于:距离 = 速度 ✖ 时间 。两帧画面之间的变化基于两帧之间间隔的时间Time.deltaTime。要记住Updata函数是每帧执行

1.1.4 读取和处理输入

  • Unity 支持的输入设备
    如:键盘⌨、鼠标🖱、手柄🎮等。
    Unity 支持的多种输入设备
  • Input.GetAxis函数
    示例代码如下
        void Update()
        {
            float v = Input.GetAxis("Vertical");
            float h = Input.GetAxis("Horizontal");
            Debug.Log("当前输入 纵向:" + v + "横向:" + h);
            transform.position += new Vector3( h*speed, v * speed, 0);
        }
    
    Input.GetAxis返回取值范围为[-1,1]的float类型值。若传入参数"Vertical"表示返回沿纵轴的输入,传入参数"Horizontal"表示返回沿纵轴的输入。上述代码可能存在问题,那就是针对帧率不同按键后小球速度不一致,所以应再乘以Time.deltaTime
  • 字符串拼接

1.1.5 实例:实现一个移动的小球

  • 代码如下:
	using UnityEngine;
	
	public class SphereScript : MonoBehaviour
	{
	    public float speed = 10;
	    // Start is called before the first frame update
	    void Start()
	    {
	        Debug.Log("组件执行开始函数!");
	        gameObject.GetComponent<Renderer>().material.color = Color.red;
	        transform.position = new Vector3(0, 0, 5f);
	    }
	
	    // Update is called once per frame
	    void Update()
	    {
	        float v = Input.GetAxis("Vertical");
	        float h = Input.GetAxis("Horizontal");
	        Debug.Log("当前输入 纵向:" + v + "横向:" + h);
	        transform.position += new Vector3( h * speed * Time.deltaTime, v * speed * Time.deltaTime,0);
	    }
	}
  • 使用上述代码拖动到小球上,调整摄像机的Rotation朝向为(0,0,0),运行即可移动小球。
  • 代码解读
    public float speed = 10;(设置速度)
    gameObject.GetComponent().material.color = Color.red;(设置小球颜色
  • 注意事项
    • 脚本中的public类型变量可以在Inspector窗口看到和修改。若将public改为private,则变量在窗口中不可见、不可改
    • 不同条件下修改脚本中的变量值有不同的作用时间(如下表所示)
值类型脚本中未运行时Inspector窗口中运行时Inspector窗口中
作用时间脚本创建后永久运行中

 创建脚本时设置了公开(public)变量,则其代码中的初始值会生效。
 当运行时,在Inspector窗口对脚本中的public变量进行修改,会在当次运行的以后时间里生效。
 当未运行时,在Inspector窗口对脚本中的public变量进行修改,会在当前Unity 项目窗口中生效。退出项目窗口时若选择Save保存,则其值会在项目中生效。
以上内容意味着:
  当创建完脚本后,每一次修改脚本中的值,但在Unity 项目中不会生效。
  当游戏运行中,修改变量,游戏结束后修改的值不会保存。(若在游戏中时事调整参数,对需要保存的数据应以记录)
  当游戏未运行时,修改变量,以后每一次运行值都会生效。如果退出项目窗口时保存,则下一次打开项目窗口也会生效。

1.2 触发器事件

触发器是一个组件,它定义了一个范围。当其他带有碰撞体组件的物体进入了这个范围时,就会产生一个触发事件脚本捕捉到这个事件的时候,就可以做出相应的处理

1.2.1 创建触发器

Unity 中,触发器和碰撞体共用了同一组件:Collider,实际上两者是不同的概念。创建一个Cube,它自带一个碰撞器在Inspector窗口勾选Box Collider面板中的 Is Trigger 选项,碰撞体就变成了同样外形的触发器。对小球和Cube都添加一个Rigibody(刚体)组件,勾选组件中的 Is Kinematic(动力学)选项,若不勾选物体会一直下落。

1.2.2 触发器事件函数

碰撞和触发总是发射在两个物体之间,所以根据不同情况,可以选择其中一个物体进行碰撞或者触发的处理。给Cube添加一个脚本,并且脚本内容如下。

	using System.Collections;
	using System.Collections.Generic;
	using UnityEngine;
	
	public class Coin : MonoBehaviour
	{
	    // Start is called before the first frame update
	    void Start()
	    {
	        
	    }
	
	    // Update is called once per frame
	    void Update()
	    {
	        
	    }
	    private void OnTriggerEnter(Collider other)
	    {
	        Debug.Log(other.name + "碰到了我");
	    }
	}

 运行游戏,在场景中拖拽球体,让它和立方体接触,就可以看到碰撞出发信息了。

  • 注意事项
    在游戏中进行的修改游戏结束后会还原,即使是在游戏中对物体添加了组件,游戏结束后也会还原运行前状态。
    如若球体没有Rigidbody组件,则不会出发碰撞消息。

1.2.2 实例:吃金币

文中内容引用或参考《Unity3D脚本编程与游戏开发》马瑶-沈琰

举报

相关推荐

0 条评论