跟练b站up 大家好我是冯无敌 的独立游戏跟练系列的记录,主要是对up的教学内容做一个比较主观的笔记,方便跟上思路和日后回顾。
上一篇详细记录了跟练过程中用到的编辑器的各项功能。本篇主要记录一下跟练编写脚本代码过程中遇到的环境配置问题,以及在unity中使用C#脚本,对物体组件中的变量进行简单调整的方法。
一、编写简单脚本时的环境配置问题
首先是安装unityhub时遇到 visual studio 报错的问题。由于我的电脑已经安装了 visual studio 2022, unity 没有自动下载并做好关联,发生了报错。想要正常的在unity编辑器里直接打开visual studio 2022编写脚本,需要进入编辑器后自行在编辑菜单 Edit→ Preferences→ External Tools→ External Script Editor 的下拉菜单中选择 visual studio 2022. 这样打开脚本时就会自动启动visual studio 2022进行编辑。
之后是visual studio 2022 安装unity相关依赖的问题。如果已经下载好的 visual studio 没有配置好相关的组件,就无法在编写代码时提供提示词或是相关的编写错误的提醒,大大影响编写效率。可以打开visual studio installer 管理已经安装好的 visual studio。
点击修改,勾选使用unity的游戏开发。其他工具集选项如 .NET Muti-platform App UI 开发或是组件可以根据需要安装。
之后再打开脚本,可以看到vs2022界面左上角标签显示为Assembly CSharp,表示visual studio支持C#编写。在创建变量时输入unity相关类出现提示词,说明visual studio提供了unity相关支持。
二、简单脚本编写
在编辑器的Assets目录内创建Script文件夹,在文件夹中创建第一个C#脚本文件,命名为Nodes。
从unity默认创建的脚本文件自带一个基类MonoBehaviour,基类当中默认有两个方法,Start方法只在创建对象时被调用一次,是进行初始化的地方。Update方法在游戏的每一帧都会调用一次,用于处理游戏对象的帧更新。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class NewBehaviourScript : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
}
}
打开脚本文件,首先在默认内容中添加如下内容:
using System;
using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
public class Nodes : MonoBehaviour
{
public UnityEngine.Object nodeButton; //节点按钮
public TextMeshProUGUI nodeTitle; //节点标题
// Start is called before the first frame update
void Start() //Start:创建对象时会调用一次的方法
{
Debug.Log($"The Length of the Title is:{nodeTitle.text.Length}" ); //在""前加上 $ 表示开启插值
}
// Update is called once per frame
void Update() //Update:在游戏中每帧都会调用一次的方法
{
}
}
public在类中创建两个变量,一个nodeButton用来保存节点按钮,一个nodeTitle用来保存节点标题。在start中输入Debug.Log语句,用来在游戏控制台输出debug日志信息。
在类当中用public创建的变量称为成员变量,也可以称为属性或字段。这些变量可以在类的内部、构造函数中、或者在类的外部通过实例化对象来赋值。
其中引号前的$,表示在字符串中使用字符串插值对字符串格式化。这样会读取字符串里大括号{}包裹的变量信息。
其中的变量nodeTitle.text.Length可以理解为标题的. 文本的. 长度。
三、通过脚本对unity物体的属性变量进行操作
1.在unity操作界面上给变量赋值
在unity操作界面选择nodes,在右侧inspector菜单点击add component,将刚刚编写过的脚本附加上。给Node Button 和 Node Title,也就是刚刚在脚本中创建的两个变量赋值。可以从输入框后面的下拉菜单选择,也可以直接从hierarchy菜单拖选。
运行测试,可以看到控制台输出了按钮标题的长度,退出测试,将text的内容修改为“初始节点”,再运行测试,控制台输出了长度变为4。这表示我们给脚本的变量成功进行了赋值。
2.在C#脚本里改变物体组件中的变量
选择button后,默认组件rect transform可以修改其尺寸大小,适当调整后发现,将width修改为100比较合适。
回到vs2022继续编写代码。
void Start()
{
//Debug.Log($"The Length of the Title is:{nodeTitle.text.Length}" ); //在""前加上 $ 表示开启插值
//nodeButton.GetComponent<Transform>().GetComponent<RectTransform>().sizeDelta
//从按钮获取Transform组件,然后从Transform组件获取RectTransform组件,然后获取sizeDelta属性,比较臃肿,考虑临时变量
Transform buttonTrans = nodeButton.GetComponent<Transform>();
//临时变量获取按钮的Transform组件
RectTransform buttonRectTrans = buttonTrans.GetComponent<RectTransform>();
//再次用临时变量获取按钮的rectTransform组件
Debug.Log($"The size of the Button is: {buttonRectTrans.sizeDelta}");
}
为了让按钮宽度随着字符长度增加而增加,需要修改按钮宽度,也就需要先获取按钮大小信息的变量。
获取变量可以直接用
nodeButton.GetComponent<Transform>().GetComponent<RectTransform>().sizeDelta
这样一连串的调用变量获取。
读取物体的变量更好的方式是在方法当中创建临时变量,逐层调用物体组件引出需要的变量,这样可以很好改善代码的可读性。
通过debug信息验证获取到了想要的包含按钮尺寸的变量:
继续加几行代码。
void Start() //Start:创建对象时会调用一次的方法
{
//Debug.Log($"The Length of the Title is:{nodeTitle.text.Length}" ); //在""前加上 $ 表示开启插值
//nodeButton.GetComponent<Transform>().GetComponent<RectTransform>().sizeDelta
//从按钮获取Transform组件,然后从Transform组件获取RectTransform组件,然后获取sizeDelta属性,比较臃肿,考虑临时变量
Transform buttonTrans = nodeButton.GetComponent<Transform>(); //临时变量获取按钮的Transform组件
RectTransform buttonRectTrans = buttonTrans.GetComponent<RectTransform>(); //再次用临时变量获取按钮的rectTransform组件
Debug.Log($"The size of the Button is: {buttonRectTrans.sizeDelta}");
//想要调整按钮的长度,就想到先获取文本的长度
//文本在unity中通过TextMeshProUGUI变量形式存在,调用其中的fontSize属性
TextMeshProUGUI textMeshProUGUI = nodeTitle.GetComponent<TextMeshProUGUI>();
int fontSize = (int)textMeshProUGUI.fontSize; //fontSize属性默认为float类型,这里在前加上(int)显式转换为int类型
Debug.Log($"The fontSize of the text is: {fontSize}");
//文本长度为fontSize*.text.Length,将文本长度加在原来的Button宽度上就可以实现动态调整按钮宽度的功能。
int widthAdjust = fontSize * nodeTitle.text.Length;
buttonRectTrans.sizeDelta = new Vector2(fontSize * 2 + widthAdjust, buttonRectTrans.sizeDelta.y);
//这句看起来长,其实就是把widthAdjust这个变量加到了sizeDelta这个二位变量的第一维x上
//这里的这种调整变量大小的方法,在右侧new了一个临时变量以便对原变量进行修改
//右侧调用的变量值会使用修改前的值,左侧代表赋值的目标
}
首先通过和上面的代码一样的方式,用临时变量把标题的textMeshProUGUI组件提取出来,目的是方便提取字体大小fontSize。
提取出fontSize后为了方便后续对sizeDelta的整数操作,建立整数int型变量fontSize把原本的浮点数float型属性显式转换为int型。
int fontSize = (int)textMeshProUGUI.fontSize;
最后修改按钮宽度,按钮尺寸信息在二维向量buttonRectTrans.sizeDelta中,为了对已有变量进行修改,用new临时创建二维向量对象,即new Vector2。vector2是一个c#中的构造函数,表示创建一个二维向量。
buttonRectTrans.sizeDelta = new Vector2(x, y);
在vector2的括号中进行修改,x值改为在文本整体长度的基础上加两个字的长度,y值保持和按钮原来的值相同。
Vector2(fontSize * 2 + widthAdjust, buttonRectTrans.sizeDelta.y)
这样就实现了按钮宽度随着文本长度变化而动态适应的功能。
可以看到游戏运行后节点的宽度会随着字数的增加动态变宽,同时两侧保持一个字符的空余。
不过在游戏未运行时,脚本没有被调用,按钮宽度还是一开始的默认值100。