书籍作者: 金玺曾 著
ISBN:9787302525813
推荐程度: 无编程基础的新手,不推荐。
在学习 Unity 3D 的过程中,从图书馆借来了此书。该书最新为第四版,于2019年4月出版。在阅读学习过程中,发现书中存在不少瑕疵,特此记录,防止重复踩坑。
书中大部分工程使用的 Unity 版本为 2018.2.6f1,本人使用的 Unity 版本为 2019.4.31f1c1 。版本不同,部分界面和功能也存在差异,过时的函数也会列入勘误项。
第 1 章 Unity 基础
- 第 5 页的 Survival Shooter Tutorial 在 Unity Assets Store 已经无法找到,随便下个免费的看看即可,这个工程后续没有用到,这里只是举例使用官方商店。
第 2 章 太空射击游戏
-
第 27 页的设置星空背景的材质 Shader 为 Unlit/Texture, 这里2019的界面直接搜
Unlit
是无法出这个 Shader, 要搜索Texture
, 选择Texture / Unlit/Texture
才行。 -
第 30 页按照步骤设置完星空的动画效果之后,会发现动画根本不能循环,这里指的是图片虽然会将 OffsetY 的值从 0 变为 -1,但是界面效果并非星空在不断前进,而是一张图慢慢滚过,已经隐藏的部分不会接在尾部。坑!这里需要找到星空素材的 png 图,在 Inspector 里找到 Warp Mode 值改为 Repeat ,这样星空才能不断滚动。
-
第 36 页右键 Create -> Prefabs 创建空的预置体,这个在 2019 无法实现,除非选中一个 FBX 素材可以创建 Prefab Variant,所以还是放到 Hierarchy 上再拖入 Project 就好。
-
第 49 页提到 Gizmos 文件夹的创建,这里注意是在 Assets 文件夹里面创建,它这里表述为在 Project 窗口的根目录创建,很不准确。
-
第 50 页创建 UI 界面,刚来使用 Unity 的新手,要注意此处创建的 UI 界面均基于 XY 坐标系,即在三维坐标中垂直于 Z 轴,Z 为 0。可以理解为,UI界面在游戏世界的头顶,有另一个摄像机会把 UI 界面投射到玩家屏幕。
-
第 54 页 Player.cs 中的 OnTriggerEnter 条件判断,不能直接写
other.tag != "PlayerRocket"
这里会出现玩家飞船与后面书籍中添加的 Quad 射线碰撞层发生碰撞,所以最好换成other.tag == "Enemy" || other.tag == "EnemyRocket"
。 -
第 54 - 55 页, 创建了一个类名为
TitleScreen
的脚本,但文件名竟然是TitleSceen.cs
,低级拼写错误,需与类名保持一致。 -
第 55 页创建 UI -> Image 时,选择背景贴图,这里说默认 png 是 Texture 类型。而 2019 里默认就是 Sprite 类型,也不存在 Texture 类型,可直接选择使用。
-
第 60 页创建 ProcessModel.cs 文件,其中这句代码无法使用。
GameObject tar = AssertDatabase.LoadAssetAtPath<GameObject>(importer.assetPath);
这里始终获取的 tar 值为 null 。同时存在过时函数,原语句PrefabUtility.CreatePrefab("Assets/Prefabs/Enemy2c.prefab",tar);
,在 2019 替换为PrefabUtility.SaveAsPrefabAsset(tar, "Assets/Prefabs/Enemy2c.prefab");
第 3 章 第一人称射击游戏
-
第 72 页锁定鼠标的代码过时,原代码
Screen.lockCursor = true;
,在 2019 更改为Cursor.lockState = CursorLockMode.Locked;
。 -
第 74 页设置 Navigation Static 时,应注意 level 模型下面的三个 GameObject 也需要选中并设置,不然无法使用 Navigation 窗口的 Bake 功能,会导致敌人 AI 原地踏步。
-
第 77 页设置动画的过渡条件时,应注意选中连接线后,将
Has Exit Time
选项去掉勾选,不然敌人在执行动画的时候,即使达成了条件,会延迟触发条件,而不是只触发一次。例如,敌人 attack 一次应立即 idle ,如果不取消该选项,则会延迟进入 idle ,导致多次进入 attack 的错误逻辑。 -
第 91 页为敌人设置在小地图上显示的球体,此处没有详细说明步骤,新手比较费解。 其中描述:
创建一个球体并命名为 dummy,将其材质设置为 Self-Illumin / Diffuse
。这里实际步骤应为,在 Project 窗口内,右键 Create -> Material ,创建一个材质球,并将其颜色 Main Color 调整为 #FF0000 ,其 Shader 设置为Legacy Shaders / Self-Illumin / Diffuse
,需要注意的是 2019 内,直接搜索Legacy
或Self-Illumin
均无法查到,需输入Diffuse
再从列表中选择。创建材质球后,打开Zombie
的 prefab ,在其下面右键 Create -> 3D Object -> Sphere , 命名为 dummy 并设置材质为刚创建的 Red 材质球。
第 4 章 塔防游戏
-
第 121 页遍历敌人,需要在敌人脚本初始化时,往公共数组更新敌人。而此处描述为
打开 Enemy.cs 脚本, 在 Start 和 DestroyMe 函数中分别更新 List 中的敌人
。这里忽略了 AirEnemy.cs 脚本, 因为 Start 是私有函数,即使 AirEnemy 继承 Enemy,私有函数也不会生效, AirEnemy.cs 也需要在 Start 内加上更新 List 的语句,而 DestroyMe 是公有函数,直接继承。 -
第 127 页 Archer.cs 中函数过时,原代码为
Vector3 pos = this.m_model.transform.FindChild("atkpoint").position;
,在 2019 应改为Vector3 pos = this.m_model.transform.Find("atkpoint").position;
。 -
第 131 页为敌人添加血条 UI 代码,不仅需要为 Enemy.cs 添加,同样也需要为 AirEnemy.cs 添加, 将新增的变量改为
protected
类型,并把void Start()
改为protected
,或者直接在 AirEnemy.cs 中粘贴相同代码。这样所有敌人才会渲染血条。
第 6 章 与 Web 服务器的交互
-
第 168 页, WWW 类在 2019 以后不再推荐使用,取而代之的是 UnityWebRequest, 代码修改为
UnityWebRequest www = new UnityWebRequest.Get("http://127.0.0.1/test.php?username=get&password=12345");
,获取文本代码改为m_info = www.downloadHandler.text;
。 -
第 169 页, POST 方法的使用也已经弃用,应改为以下代码
List<IMultipartFormSection> formData = new List<IMultipartFormSection>();
formData.Add(new MultipartFormDataSection("username", "post"));
formData.Add(new MultipartFormDataSection("password", "6789"));
UnityWebRequest www = UnityWebRequest.Post("http://127.0.0.1/test.php", formData);
yield return www.SendWebRequest();
- 第 170 页,关于上传/下载图片的方法也发生了改变。2019 版本后可修改为以下代码:
byte[] bs = m_uploadImg.EncodeToJPG();
List<IMultipartFormSection> formData = new List<IMultipartFormSection>();
formData.Add(new MultipartFormFileSection("image", bs, "screenshot", "image/jpeg"));
// POST 文件数据
UnityWebRequest www = UnityWebRequest.Post("http://127.0.0.1/test.php", formData);
yield return www.SendWebRequest();
// ...
// 接收部分
m_downloadImg = new Texture2D((int)img.rectTransform.rect.width, (int)img.rectTransform.rect.height);
m_downloadImg.LoadImage(www.downloadHandler.data);
Sprite sprite = Sprite.Create(m_downloadImg, new Rect(0, 0, m_downloadImg.width, m_downloadImg.height), new Vector2(0.5f, 0.5f));
img.sprite = sprite;
- 第 172 页,同理下载声音文件也更换了方法。当使用 GET 请求时,多媒体文件的下载有特殊的类配合使用,2019 版本后可使用以下代码:
UnityWebRequest www = UnityWebRequestMultimedia.GetAudioClip("http://127.0.0.1/music.wav", AudioType.WAV);
yield return www.SendWebRequest();
if (www.isNetworkError || www.isHttpError)
{
this.updateResult(www.error);
yield return null;
}
else
{
if (www.isDone)
{
m_soundClip = DownloadHandlerAudioClip.GetContent(www);
GetComponent<AudioSource>().PlayOneShot(m_soundClip);
}
}
- 第 176 页,定义的用户数据类,如果使用 Unity 自带的 JsonUtility 进行 JSON 序列化,需要在对应类上添加
[Serializable]
特性。同时,需要注意的是,JsonUtility 的FromJson()
方法,区分大小写,并且不支持属性的序列化。在 Unity 内声明序列化类时,只能使用字段,而不能声明为属性。例如:
// 正确的声明
[Serializable]
public class HighScore
{
public int? id;
public string name;
public int score;
}
// JsonUtility 无法转化的声明
[Serializable]
public class HighScore
{
public int? id { get; set; }
public string name { get; set; }
public int score { get; set; }
}
第 7 章 TCP UDP 实例
- 第 185 页 这里的 TCP 服务器代码里,作者的变量命名有些错误,在之前的章节也有出现。例如,把长度
int length
经常写成int lenght
,估计是写高度写惯了int height
。
第 10 章 Android 游戏移植
- 第 262 页的 AssetBuilder.cs 内, BuildAssets 方法内应优先判断路径是否存在,否则路径不存在时报错。可参照第 264 页的 BuildAssetsAuto 方法前几行:
string path = "Assets/Bundle/Win";
if (!System.IO.Directory.Exist(path){
System.IO.Directory.CreateDirectory(path);
}
不过,如果使用的是UnityEngine.Windows.Directory.CreateDirectory
方法,不会自动创建不存在的子目录。
第 11 章 Unity 新 GUI 完全攻略
-
第 275 页这里提到选择
Create Editable Copy
创建出字体副本,这时候在 Project 窗口会出现三个文件,分别是arial.fontsettings
、arial.mat
和arial_copy.png
,这里需要把前两者都重新命名为arial_copy
,不然字体选择里会识别两个为arial
字体。 -
第 276 页,这里提到显示字体可能是白色的,无法显示 PS 中的艺术字体。需要在 Project 窗口,选中替换的
arial_copy.png
图片,在 Inspector 窗口中检查设置Alpha Is Transparent
已勾选,同时 Default 选项卡中的Format
应选择Automatic
或者RGBA 32bit
,如果选择的是Alpha 8
则图片会变成黑白。 -
第 283 页,2019 的 Inspector 窗口中将选中颜色
Selected Color
也可以单独设置,所以文中描述Highlighted Color
不仅为高亮状态,还代表选中状态,在 2019后的版本不适用。
网友评论