官方教程:Creator Kit: Beginner Code

下载项目:Unity Asset Store: Creator Kit: Beginner Code | URP

在Creator Kit: Beginner Code | URP中学习Unity中C#代码编写。


unity中无法保存项目怎么?

在菜单中选择File -> Exit,在Keep Project?对话框中选择Keep,将项目保存到方便的位置。


1、准备开始

① 创建一个Unity工程,2D或3D都行;

② 在Unity Asset Stroe获取Creator Kit: Beginner Code,下载并导入工程;

③ 熟悉Unity基本概念,Scene、游戏对象、预制件Prefab等;

④ 尝试游戏:将Creator Kit: Beginner Code包中的ExampleScene导入,开始Play。主要功能包括:

导航、物品栏、角色属性。

2、了解编程

① 程序设计语言是形式语言,由一组明确的规则构成。不像自然语言那样时刻发展、复杂且有着细微的差别。在Unity中使用C#语言;

② 将C#代码组织为脚本Scripts,即一组指导PC做特定事情的指令。将指令分到不同的脚本中有助于在不同项目中重用代码、快速地查找和更改信息、更细致地组织工程。

例如,在Creator Kit: Beginner Code中的脚本不大,但是与大型脚本有着相同的基本原则。

③ 脚本通过作为部件component附着到游戏对象上来控制游戏对象的行为。

例如,在Creator Kit: Beginner Code包中,选择PotionSpawner游戏对象的Spawner Sample (Script)部件。点击该部件的名称,在Project中双击打开,该脚本将在VisualStudio中打开。

Visual Studio Code编辑器识别不了UnityEngine.UI命名空间:删掉项目csproj文件,Unity中选择Microsoft Visual Studio启动(注:要勾选Generate all .csproj files),Unity会生成需要的csproj,之后就可以切回Visual Studio Code快乐的开发了。

using UnityEngine;
using CreatorKitCode;

public class SpawnerSample : MonoBehaviour
{
    public GameObject ObjectToSpawn;

    void Start()
    {
        int angle = 15;
        Vector3 spawnPosition = transform.position;
        Vector3 direction = Quaternion.Euler(0, angle, 0) * Vector3.right;
        spawnPosition = transform.position + direction * 2;
        Instantiate(ObjectToSpawn, spawnPosition, Quaternion.identity);

        angle = 55;
        direction = Quaternion.Euler(0, angle, 0) * Vector3.right;
        spawnPosition = transform.position + direction * 2;
        Instantiate(ObjectToSpawn, spawnPosition, Quaternion.identity);

        angle = 95;
        direction = Quaternion.Euler(0, angle, 0) * Vector3.right;
        spawnPosition = transform.position + direction * 2;
        Instantiate(ObjectToSpawn, spawnPosition, Quaternion.identity);
    }
}

④ 掌握C#基本语法。(至少变量、赋值、函数、类)

3、编写简单指令

Unity脚本API:https://docs.unity3d.com/ScriptReference/index.html

① 在API参考中查找各个属性/方法的含义:

transform.position,是Vector3类,游戏对象Transform组件的position属性(在Inspector中也可以看导),改变position可以移动,获取position可以定位。

Vector3:代表3D的向量和点,用于传递3D位置和方向,以及一般的向量操作。其中right属性是(1, 0, 0)的简写。

Quaternion:代表旋转,紧凑易插值。用复数表示旋转,一般使用其方法。*操作符代表对一个旋转或向量执行向左/右旋转。Quaternion.Euler(float x, y, z)返回一个旋转,在x/y/z轴旋x/y/z度。

② 新增一个变量radius,并赋值为5,将原脚本中的距离2替换为radius,就可以使生命药水的生成距离变远,并且对三个对象只需要修改一个参数。

// 修改的部分
float radius = 5;
spawnPosition = transform.position + direction * radius;

③ 在Inspector窗口中,点击脚本中的“Save State”按钮,可以保存当前版本。之后可以通过“Restore”按钮回退到之前的版本。

4、使用函数生成物品

函数就是指令集。编译器在访问函数时会告诉计算机先完成(或执行)该指令集内的所有指令,然后再继续执行脚本的其余部分。使用函数,可以降低代码的重复。

Unity 有一些使用特殊名称并在游戏中特定时刻调用的特定函数,脚本中的void Start() {}就是其中之一。Start 函数是在场景开始时调用的函数。

① 将第2节的脚本中的重复部分提炼为一个函数:

using UnityEngine;
using CreatorKitCode;

public class SpawnerSample : MonoBehaviour
{
    public GameObject ObjectToSpawn;

    void Start()
    {
        SpawnPotion(15, 5.0f);
        SpawnPotion(55, 5.0f);
        SpawnPotion(95, 5.0f);
        SpawnPotion(135, 9.0f);
    }
    void SpawnPotion(int angle, float radius)
    {
        Vector3 spawnPosition = transform.position;
        Vector3 direction = Quaternion.Euler(0, angle, 0) * Vector3.right;
        spawnPosition = transform.position + direction * radius;
        Instantiate(ObjectToSpawn, spawnPosition, Quaternion.identity);
    }
}

② 只需要调用生成药水的函数就可以生成。

5、使用类创建游戏对象

函数将不同的指令组装在一起,而类将不同的变量、函数组装在一起。通过将函数和变量分组到一起,可以高效地组织代码。使用“.”运算符来访问类的成员。声明一个新的对象,须使用new关键字。例如,第2节中的class SpawnerSample{ } 就是声明了一个类,通过这个类可以生成药水;

类有访问权限,类中的成员也有访问权限,访问权限分为public公有和private私有。将类变量设为公共变量,可以从 Inspector 访问这个变量。

将SpawnerSample类中的ObjectToSpawn设为公有后,就可以通过指定预制件来生成不同种类的游戏对象。通过公有变量,无需编辑脚本即可调整游戏玩法,包括对象的速度、装备后的属性、敌人的碰撞点。

仿照生成药水的过程,创建一个生成金币的游戏对象:

① 在Hierarchy中生成一个新的Sphere对象,并命名为MoneySpawner;

② 在Inspector中为MoneySpawner增加SpawnerSample脚本属性;

③ 将预制件MoneyLoot添加到SpawnerSample中的ObjectToSpawn。

补充:继承自MonoBehaviour

MonoBehaviour是一个基类,所有Unity的脚本都派生自该类。在使用C#时,必须必须明确定义继承MonoBehaviour。例如,第2节中的class SpawnerSample : MonoBehaviour 就是说明SpawnerSample派生自MonoBehavior,Start()方法就是继承自MonoBehavior的方法。

父类就是对一系列有相同行为的类的相同部分做了更高层的抽象。例如,所有的脚本都需要在场景建立时执行,但是执行的动作可能不同,因此在MonoBehavior中声明了一个Start(),而继承MonoBehavior的方法重写Start方法,使其有不同的实现。

6、增加物品效果

为生命药水增加一个效果,使用后可以增加10点生命:

① Creator Kit项目提供了一个增加模板效果的脚本模板:菜单-> BeginningCode -> Create Item Effect,创建AddHealthEffect脚本,在Project中打开该脚本;(该脚本存在于 Assets 文件夹中,已经过编译,并成为游戏代码的一部分,即可以将其分配给游戏中的生命值药水。)

② 在Project中选择Potion预制件,为AddNewEffect属性添加AddHealthEffect脚本,在Description属性中可以输入脚本描述“Give 10 Health”;

③ 修改AddHealthEffect脚本使之符合条件:

此Creator Kit项目有一个特殊的 StatSystem 系统来控制角色的统计信息。将 CharacterData 脚本作为组件附加到某个游戏对象后,该游戏对象即可访问创作者套件的 StatSystem,使用 ChangeHealth()

将生命值增加量设为公有变量,可以在Inspector窗口修改。

Use函数返回一个布尔值,返回true表示已使用物品,并将物品数量减1,返回false表示无法使用。

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

public class AddHealthEffect : UsableItem.UsageEffect
{
    public int HealthAmount;

    public override bool Use(CharacterData user)
    {
        user.Stats.ChangeHealth(HealthAmount);
        return true;
    }
}

7、创建可用物品

可用物品是玩家可以通过双击自己背包中的物品来使用的物品(例如,生命值药水)。

① 在Assets中创建一个UsableItem,并设定名称;

② 增加使用效果及物品返回值。使用效果脚本指定在玩家背包中双击可用物品时会发生什么情况,该脚本在编辑器中添加到可用物品资源。方法同第6节;

③ 将使用效果添加到可用物品。

8、创建装备用品

装备物品是在装备后赋予玩家角色特定属性的物品(武器是一种具有附加功能的特殊装备物品)。可以给装备物品指定:一个最低的统计要求,只有在玩家达到最低要求后才会进行装备(例如,只有当玩家的 HP 超过 5 时才可以装备某个物品)。一个装备效果,可以在装备物品时为玩家角色添加效果(例如,提高统计数值)。

① 在Assets中创建一个EquipmentItem,并设定名称;

② 增加装备效果:菜单-> BeginningCode -> Create Equipped Effect,创建EquippedEffect脚本,在Project中打开该脚本并编辑;

public class EFFECTNAME : EquipmentItem.EquippedEffect
{
     public override void Equipped(CharacterData user)
     {
     // +1 Strength
     }
     
     public override void Removed(CharacterData user)
     {
     // -1 Strength
     }
}

③ 将装备效果添加到装备物品。

9、创建武器

武器是一种可以在角色武器槽位中装备的特殊装备物品。除了普通装备物品的功能外,还可以给武器指定:与攻击行为有关的统计信息:Reach、Speed、Minimum Damage 和 Maximum Damage。一个武器攻击效果,可让你自定义在武器对敌人角色造成伤害时出现的情况。

① 在Assets中创建一个Weapon,并设定名称,在Inspectot中,除了装备用品的字段外,还可以看到Weapon Stats、Add New Weapon Attack Effect;

② 增加攻击效果:菜单-> BeginningCode -> Create Weapon Attack Effect,创建WeaponAttackEffect脚本,在Project中打开该脚本并编辑;

public class EFFECTNAME : Weapon.WeaponAttackEffect
{
    public override void OnAttack(CharacterData target, CharacterData user, ref Weapon.AttackData attackData)
    {
    // 控制武器击中敌人时发生的情况,例如伤害效果attackData.AddDamage
    }
    
    public override void OnPostAttack(CharacterData target, CharacterData user, Weapon.AttackData data)
    {
    // 执行所有 OnAttack 函数指令后将调用此函数。此函数可用于自定义在应用所有 OnAttack 效果后对于目标所受到的总伤害量做出的反应。
    // 例如,可以使用此函数将对敌人的伤害百分比转换为玩家角色的生命值。
    }
}

③ 将武器攻击效果应用于武器;