meta data for this page
  •  

📚 差别

这里会显示出您选择的修订版和当前版本之间的差别。

到此差别页面的链接

两侧同时换到之前的修订记录前一修订版
后一修订版
前一修订版
scripting:client:core [2025/06/13 07:52] – 移除 - 外部编辑 (Unknown date) 127.0.0.1scripting:client:core [2025/08/16 04:04] (当前版本) bibiboxs
行 1: 行 1:
 +<markdown>
 +# ==Client/Core==
  
 +==**在当前版本下,`Client`脚本更适合实现客户端独有的功能、GUI界面等。**==
 +
 +==**有关世界内容的玩法(如:Player、Character、Vehicle等)建议优先使用`World`脚本实现。**==
 +
 +> 如果有某些功能只有ClientAPI支持,可以用`RPC\CMD`相关方法与服务端进行二次通信,以实现**“通过服务端让某个玩家执行一个ClientAPI”**。
 +
 +[note2]
 +注意:客户端脚本是只读的,无法由API写入任何文件(除游戏选项外)。
 +[/note]
 +
 +
 +
 +## Event
 +
 +### OnScriptLoad()
 +
 +> 当**客户端脚本**被完整加载后调用,==部分API需要放置在此事件执行才有效,因为至此脚本才加载完毕==。
 +
 +> **注意:此事件并非是客户端首个运行事件,通常会等待`Player`完整加载后才会执行,因此部分有关`OnPlayerXXX`的事件可能会更加提前。**
 +
 +[note3]
 +**注意:此事件是真正意义上的“脚本加载完成”,因此如果有代码放置在JavaScript空白区域,并不一定会按照预期正确执行,有关初始化的代码建议放置在此处执行。**
 +[/note]
 +
 +```javascript
 +BindKey(...); //Invalid, Script not loaded
 +
 +function OnScriptLoad()
 +{
 + BindKey(...); //Correct
 +}
 +```
 +
 +
 +
 +### OnScriptUnload()
 +
 +> 当脚本即将被释放时调用。
 +
 +
 +
 +### OnFrameUpdate( deltaTime )
 +
 +> 当脚本加载完成后**每帧**调用。
 +
 +由于此事件属于**客户端脚本**范畴,所以可以理解为每帧渲染事件,无须担心延迟问题。
 +
 +```
 +deltaTime:float //增量时间
 +```
 +
 +
 +
 +### OnLocalCommand( cmd, arg )
 +
 +> 当本地客户端**发送一条指令之前**调用(玩家本地输入指令发送)。
 +>
 +> 此事件将决定是否投递指令到服务端,如果返回`true`(或忽略)则**默认**投递,否则返回`false`则拦截此指令,不会发送到服务端执行。
 +
 +此事件可供实现一些内置的“本地游戏指令”,例如可实现输入`"quitgame"`退出游戏等功能。
 +
 +**注意:对于少数引擎内置的指令(如`quit\q\version\disconnect...`)不会被接收和调用,这是不可拦截的。**
 +
 +
 +
 +### OnCameraObserver( character )
 +
 +> 当客户端`Camera.Target`发生变化时调用。
 +
 +
 +
 +### OnServerNetworkRPC( rpc, arg0, arg1, arg2 )
 +
 +> 当接收到来自服务端发送的**RPC消息**时调用,**这是客户端与服务端传输自定义信息的方式之一**。
 +>
 +> **对于一些特殊情况,可以利用`json`进行更详细的内容传输。**
 +
 +[note2]
 +
 +注意:`CMD\RPC`传输支持几个基础类型(`int | float | string | bool`)。
 +
 +[/note]
 +
 +
 +
 +### OnServerStreamData( number, data )
 +
 +> 当接收到来自服务端发送的**自定义数据**时调用,**这是客户端与服务端传输自定义信息的方式之一**。
 +>
 +> 自定义信息数据由`float(int)\string`两个参数组成。
 +>
 +> **对于一些特殊情况,可以利用JSON(data参数)进行更详细的内容传输。**
 +
 +
 +
 +### OnTypingStateChange( state )
 +
 +> 当客户端**开始\结束**聊天框时调用。
 +
 +
 +
 +### OnKeyDown( keyTag )
 +
 +> 当脚本通过`BindKey() | BindNativeKey()`绑定的**按键被按下**时调用。
 +
 +```javascript
 +function OnKeyDown( keyTag ): int
 +{
 +    return 1;
 +}
 +```
 +
 +- `keyTag`:按键标签(非按键代码)
 +- `return`:是否允许传递给服务端(如果服务端监听)
 +
 +
 +
 +### OnKeyUp( keyTag )
 +
 +> 当脚本通过`BindKey() | BindNativeKey()`绑定的**按键被抬起**时调用。
 +
 +```javascript
 +function OnKeyUp( keyTag ): int
 +{
 +    return 1;
 +}
 +```
 +
 +- `keyTag`:按键标签(非按键代码)
 +- `return`:是否允许传递给服务端(如果服务端监听)
 +
 +
 +
 +### OnWorldTimeChange( oldTime, newTime )
 +
 +> 当世界时间发生改变时调用。
 +
 +```javascript
 +function OnWorldTimeChange( oldTime, newTime )
 +{
 +    DLog("OldTime: " + oldTime.Hour + "-" + oldTime.Minute);
 +    DLog("NewTime: " + newTime.Hour + "-" + newTime.Minute);
 +}
 +```
 +
 +
 +
 +### OnWorldWeatherChange( oldWeather, newWeather )
 +
 +> 当世界天气发生改变时调用。
 +
 +```javascript
 +function OnWorldWeatherChange( oldWeather: int, newWeather: int )
 +```
 +
 +
 +
 +## Function
 +
 +### Exec()
 +
 +> 执行一段脚本代码(Client\World脚本不互通)。
 +>
 +> 代码内容可能出现报错,考虑使用try\catch进行防范。
 +
 +```javascript
 +function Exec( code: string )
 +```
 +
 +
 +
 +### OpenUrl()
 +
 +> 请求访问一个**网络或本地路径**,执行后将由玩家决定是否打开Url。
 +>
 +> 如果希望访问一个本地路径(或执行),请将url路径前增加`file://`路径前缀。
 +
 +```javascript
 +function OpenUrl( url: string )
 +```
 +
 +
 +
 +### LoadNativeScene()
 +
 +> 载入一个引擎内置场景(如地图编辑器等)。
 +
 +```javascript
 +function LoadNativeScene( type: int )
 +```
 +
 +| ID   | 面板描述                          |
 +| ---- | --------------------------------- |
 +| 0    | 世界场景(相当于重载主场景)      |
 +| 1    | [地图编辑器](reference/mapeditor) |
 +| 2    | [实验工坊](reference/workshop) |
 +
 +
 +
 +### NetworkCMD()
 +
 +> 发送一条CMD指令到服务端,此功能合理使用可扩展许多效果。
 +>
 +> 服务端收到数据后,将由`OnPlayerNetworkCMD()`事件接收。
 +>
 +> **注意:`CMD\RPC`方法仅支持基础类型,并且会自动类型转换。**
 +
 +```javascript
 +function NetworkCMD( cmd: string, arg0: any, arg1: any, arg2: any )
 +```
 +
 +
 +
 +### SendDataToServer()
 +
 +> 发送一条自定义数据消息到服务端,此功能合理使用可扩展许多效果。
 +>
 +> 服务端收到数据后,将由`OnPlayerStreamData()`事件接收。
 +>
 +> **注意:这里不应该放置特别大的数据内容,否则可能造成网络阻塞。**
 +
 +```javascript
 +function SendDataToServer( number: float(int), data: string = "" )
 +```
 +
 +
 +
 +### SetOutlineColor()
 +
 +> 设置游戏内描边相关的**全局颜色**(共计3个索引`0~2`,全局共享颜色)。
 +>
 +> **注意:如果索引为`-1`可设置表面填充颜色(FillColor)。**
 +
 +```javascript
 +function SetOutlineColor( index: int, color: Color )
 +```
 +
 +
 +
 +### ScreenFade()
 +
 +> 执行一次全屏转场(`Alpha: 0 -> 1 -> 0`)。
 +
 +```javascript
 +function ScreenFade( time: float, middleTime = 0, color: Color = Color(0, 0, 0), isTop: bool = true, onMiddle = null, ignoreHit: bool = true )
 +/*
 + time:渐变时间(渐入>不透明>渐出),例如设置为2,则表示0~1秒变不透明,1~2秒变透明
 + middleTime:不透明延迟时间,默认为0,否则将等待X秒后再进行透明渐变
 + color:颜色,默认为黑色
 + isTop:是否顶层,默认为true
 + onMiddle:可选委托事件,当颜色完成不透明时调用
 + ignoreHit:转场是否屏蔽点击,默认为true
 +*/
 +```
 +
 +
 +
 +### ScreenFadeIn()
 +
 +> 执行一次全屏渐入转场(`Alpha: 0 -> 1`)。
 +
 +```javascript
 +function ScreenFadeIn( time: float, color: Color = Color(0, 0, 0), isTop: bool = true, onComplete = null, ignoreHit: bool = true )
 +/*
 + time:整体时间(渐入>不透明)
 + color:颜色,默认为黑色
 + isTop:是否顶层,默认为true
 + onComplete:可选委托事件,当颜色完成不透明时调用
 + ignoreHit:转场是否屏蔽点击,默认为true
 +*/
 +```
 +
 +
 +
 +### ScreenFadeOut()
 +
 +> 执行一次全屏渐出转场(`Alpha: 1 -> 0`)。
 +
 +```javascript
 +function ScreenFadeOut( time: float, color: Color = Color(0, 0, 0), isTop: bool = true, onComplete = null, ignoreHit: bool = true )
 +/*
 + time:整体时间(不透明>渐出)
 + color:颜色,默认为黑色
 + isTop:是否顶层,默认为true
 + onComplete:可选委托事件,当颜色完成透明时调用
 + ignoreHit:转场是否屏蔽点击,默认为true
 +*/
 +```
 +
 +
 +
 +### Transition()
 +
 +> 执行一次全屏转场特效(`Alpha: 0 -> 1 -> 0`),不同的`type`有不同的效果。
 +
 +```javascript
 +function Transition( type: int, addTime: float = 0, color: Color = Color(255, 255, 255), action: Action = null, isOut: bool = false )
 +```
 +
 +- **type:**转场特效类型
 +- **addTime:**转场中途覆盖后,等待的延迟时间(默认为`0`,即为立即渐出)
 +- **color:**转场特效颜色
 +- **action:**当转场中途完全覆盖时执行代码
 +- **isOut:**是否立即淡出
 +
 +| Type | 说明                                   |
 +| ---- | -------------------------------------- |
 +| 0    | 平滑淡入、淡出                         |
 +| 1    | 左右对撞、撞开                         |
 +| 2    | 上下对撞、撞开                         |
 +| 3    | 向右推动覆盖、继续向右移出             |
 +| 4    | 上下分别向左右推动覆盖(类似街机游戏) |
 +| 5    | 圆圈缩小覆盖、放大淡出                 |
 +| 6    | 方块旋转覆盖、类似相机镜头             |
 +| 7    | 多个方块覆盖、淡出                     |
 +| 8    | 多个菱形覆盖、淡出                     |
 +| 9    | 画笔涂擦覆盖、淡出                     |
 +| 10   | 噪声覆盖、淡出                         |
 +| 11   | 液体覆盖、淡出                         |
 +
 +
 +
 +### Message()
 +
 +> 发送一条本地客户端消息(在消息框中)。
 +
 +```javascript
 +function Message( text: string )
 +```
 +
 +
 +
 +### Announce()
 +
 +> 发送一条本地**公告\大文字**消息,具体类型样式参考[《世界资源实例汇总》](reference/instances)。
 +
 +```javascript
 +function Announce( text: string, type: int = 0, time: float = 6 )
 +```
 +
 +
 +
 +### Subtitle()
 +
 +> 发送一条本地**底部字幕**消息。
 +
 +```javascript
 +function Subtitle( text: string )
 +```
 +
 +
 +
 +### BindKey()
 +
 +> 绑定一个**脚本按键**(当前场景有效),可用于监听某个键被按下\抬起。
 +>
 +> 按键参数可填写**UnityEngine.KeyCode(Enum)**==索引或名称==作为按键参数。
 +
 +[note2]
 +多数情况下,考虑使用`BindNativeKey()`绑定按键。
 +[/note]
 +
 +```javascript
 +function BindKey( keyTag: string, key1: string, key2: string = "None", key3: string = "None" )
 +/*
 + keyTag:按键标签(用于识别)
 + key1:按键1标准名称(如'H'
 + key2:默认'None',否则表示组合键
 + key3:默认'None',否则表示组合键
 +*/
 +```
 +
 +
 +
 +### UnbindKey()
 +
 +> 取消绑定一个**脚本按键**,对其按键监听不再生效。
 +
 +```javascript
 +function UnbindKey( keyTag: string )
 +```
 +
 +
 +
 +### UnbindAllKey()
 +
 +> 取消绑定所有**脚本按键**,对其按键监听不再生效。
 +
 +```javascript
 +function UnbindAllKey()
 +```
 +
 +
 +
 +### BindNativeKey()
 +
 +> 绑定一个**模组公开自定义按键**(**支持设置界面自定义按键**),可用于监听某个键被按下\抬起。
 +>
 +> 按键参数可填写**UnityEngine.KeyCode(Enum)**==索引或名称==作为按键参数。
 +>
 +> **此方法设置的按键应该为【默认按键】,后续如果玩家自定义修改按键(例如`B`),即使代码定义的仍然是【例如`H`】,也会自动识别为玩家修改的【`B`】键。**
 +
 +```javascript
 +function BindNativeKey( keyTag: string, key1: string, key2: string = "None", key3: string = "None" )
 +/*
 + keyTag:按键标签(用于识别)
 + key1:按键1标准名称(例如'H'
 + key2:默认'None',否则表示组合键
 + key3:默认'None',否则表示组合键
 +*/
 +```
 +
 +**注意:此功能适合绑定一个【可供玩家自定义】的游戏按键,绑定后将会在【设置界面】自动出现对应的【按键绑定选项】。由于每次切换场景都会重置代码,因此如果希望玩家在主界面就可以设置按键,应该优先在`Main`场景执行此代码。**
 +
 +```javascript
 +//Main Scene
 +function OnScriptLoad()
 +{
 +    //绑定注册,【设置菜单】会出现对应的绑定选项
 +    BindNativeKey("EnterVehicle", "E"); //绑定一个E键按钮(默认按键)
 +
 +    //打开设置菜单,会出现对应的绑定按钮
 +    CreateNativeView(1);
 +}
 +
 +//Any Scene
 +function OnKeyDown( key )
 +{
 + if(key == "EnterVehicle")
 + {
 + DLog("按下进入载具按钮!");
 + }
 +}
 +```
 +
 +
 +
 +### UnbindNativeKey()
 +
 +> 取消绑定一个**模组公开自定义按键**,对其按键监听不再生效及公开。
 +
 +> **注意:如果玩家已打开【游戏设置】界面,取消绑定不会实时同步UI。**
 +
 +```javascript
 +function UnbindNativeKey( keyTag: string )
 +```
 +
 +
 +
 +### UnbindAllNativeKey()
 +
 +> 取消绑定所有**模组公开自定义按键**,对其按键监听不再生效及公开。
 +
 +> **注意:如果玩家已打开【游戏设置】界面,取消绑定不会实时同步UI。**
 +
 +```javascript
 +function UnbindAllNativeKey()
 +```
 +
 +
 +
 +### SetGameOption()
 +
 +> 绑定一个**公开游戏设置选项**,选项将会显示在**【游戏选项——模组设置】界面(`Mod.XXXXX`)**。
 +>
 +> 默认添加后没有对应翻译,因此会显示为**翻译文本路径**,可**修改\附加翻译文件**以正确显示文本。
 +>
 +> 模组选项保存路径:`Archives\package.json`
 +
 +[note2]
 +
 +注意:此方法通常只负责**公开属性占位**,除初次使用参数填写默认值外,后续即使设置了属性参数,也不会修改替换此选项(而是由玩家通过【模组设置】自行修改),**除非使用新的`KeyPath`或`value`类型发生改变(自动覆盖为新类型的默认值)**。
 +
 +==**通过此方法公开的设置选项将持续存在(即使切换场景),直到当前模组被关闭。**==
 +
 +[/note]
 +
 +```javascript
 +function SetGameOption( keyPath: string, value: any = null, param: any = null, overwrite: bool = false )
 +```
 +
 +**补充:`Mod.InternalNull`**是一个特殊空隙路径,填写此路径会默认被理解为是一个空行占位符号。
 +
 +[note2]
 +
 +以下是简单案例,通常只需在`Main`脚本绑定一次即可,后续直到模组被关闭前不会删除绑定。
 +
 +[/note]
 +
 +```javascript
 +//KeyPath
 +"Mod.XXXXX" == "XXXXX" //Easy write method
 +
 +//Example
 +SetGameOption("PlayerName", "UserName"); //InputField: default "UserName"
 +
 +SetGameOption("InternalNull"); //Null string
 +SetGameOption("FlyMode", true); //Bool Select: default true
 +SetGameOption("DamageMultiple", 50); //Progress 0~100: default 50.0 (50%)
 +SetGameOption("PlayerSkin", "0|XXX", "Pig|Dog|Cat"); //Dropdown: default "Pig" (0)
 +SetGameOption("PlayerSkin2", "2|XXX", "Pig|Dog|Cat"); //Dropdown: default "Cat" (2)
 +```
 +
 +| 表达式                        | 说明                                      |
 +| ----------------------------- | ----------------------------------------- |
 +| `0`<br />`35.0`               | 数值(可拖拽进度条),建议范围`0.0~100.0` |
 +| `true`<br />`false`           | 布尔值(选择框)                          |
 +| `Test`                        | 文本(输入框)                            |
 +| `0|0` + Param: `Item 1|Item2` | 文本+`Param`参数(选择框)                |
 +
 +
 +
 +### GetGameOption()
 +
 +> 获取一个**模组游戏设置选项**的值,可填写默认值参数(如果没有找到储存记录的话,返回`defaultValue`)。
 +>
 +> **注意:此方法将返回取得数值的最终结果(`number | bool | string`),其中==选择框类型==将直接返回索引(`number`)。**
 +
 +```javascript
 +function GetGameOption( keyTag: string, defaultValue: any = null ): any
 +```
 +
 +
 +
 +### GetModArchive()
 +
 +> **此方法已在V0.83移除。**
 +>
 +> 尝试读取**指定模组**的持久化存储数据,如不存在则返回空文本。
 +>
 +> 注意:如果不填写参数,默认获取当前模组的数据。
 +
 +```javascript
 +function GetModArchive( package: string = null ): string
 +```
 +
 +
 +
 +### GetWorldTime()
 +
 +> 获取游戏世界时间实例(`WorldTime`)。
 +
 +```javascript
 +let worldTime = GetWorldTime();
 +DLog("Hour: " + worldTime.Hour + ", Minute: " + worldTime.Minute);
 +```
 +
 +
 +
 +### GetWorldTimeRate()
 +
 +> 获取游戏世界时间速率(游戏时间每分钟的时间间隔)。
 +
 +```javascript
 +function GetWorldTimeRate(): float
 +```
 +
 +
 +
 +### GetWorldWeather()
 +
 +> 获取游戏世界天气。
 +
 +```javascript
 +function GetWorldWeather(): float
 +```
 +
 +
 +
 +### BindActionKey()
 +
 +> 绑定(更新)**行为触发按键**(类似触发`KEY: [E]`按钮)。
 +>
 +> **注意:同一个`keyTag`同时只会存在一个。**
 +
 +```javascript
 +function BindActionKey( keyTag: string, title: string = null, onAction: Action = null, isHandled: bool = true ): string
 +```
 +
 +- `keyTag`:按键标签(需由`BindKey | BindNativeKey`绑定的标签)
 +- `title`:如果不为空,则优先使用此文本(支持宏文本),否则使用默认文本
 +- `onAction`:按键按下后事件
 +- `isHandled`:是否阻止按键向下传递(`OnKeyDown | OnKeyUp`)
 +- `return`:返回UUID(用作识别)
 +
 +
 +
 +### GetActionKey()
 +
 +> 获取指定`keyTag`的**行为触发按键**UUID,如果不存在则返回`null`。
 +
 +```javascript
 +function GetActionKey(): string
 +```
 +
 +
 +
 +### UnbindActionKey()
 +
 +> 取消(移除)指定`keyTag`的**行为触发按键**。
 +
 +```javascript
 +function UnbindActionKey( keyTag: string )
 +```
 +
 +
 +
 +### UnbindActionKeyByUUID()
 +
 +> 取消(移除)指定`keyTag`的**行为触发按键**(通过UUID)。
 +
 +```javascript
 +function UnbindActionKeyByUUID( uuid: string )
 +```
 +
 +
 +
 +### UnbindAllActionKey()
 +
 +> 取消(移除)所有**行为触发按键**。
 +
 +```javascript
 +function UnbindAllActionKey()
 +```
 +
 +
 +
 +### GenerateMapSnapshot()
 +
 +> 生成游戏地图(大地图+小地图雷达)快照。
 +>
 +> 世界加载时默认会**自动生成**,如果世界布局**动态改动**过大,或者希望修改**渲染风格**时,可以手动执行一次方法。
 +>
 +> 注意:此方法会根据**地图尺寸**进行动态生成(地图越大,生成越慢),可能引起短暂卡顿。
 +>
 +> 补充:此方法允许设置`_Config.json`配置文件,以在地图加载时提前生成,避免额外的开销。
 +
 +```javascript
 +function GenerateMapSnapshot( style: int = 0, worldTime: int = 10 )
 +```
 +
 +- `style`渲染风格(0=默认;1=描边;2=油画;3=灰质;4=黑白描边;5=霓虹描边)
 +- `worldTime`世界时间(生成快照时的亮度)
 +
 +
 +
 +### SetFocusEntityDistance()
 +
 +> 设置本地玩家**焦点检测距离**(与`World`作用相同)。
 +
 +```javascript
 +function SetFocusEntityDistance( value: float )
 +```
 +
 +
 +
 +### GetFocusEntityDistance()
 +
 +> 获取本地玩家**焦点检测距离**。
 +
 +```javascript
 +function GetFocusEntityDistance(): float
 +```
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +</markdown>