话不多说,先让我们一起看看最终结果演示
那么接下来让我们从零开始制作该秋千预制体
1.首先创建一个预制体命名为swing,拖入对应的模型、触发器、交互物、空锚点
1
2
3
2.接着创建预制体脚本
4
/**
* AUTHOR: 疏影横斜水清浅
* TIME: 2023.02.22-10.20.05
*/
import Seat from "./Seat";
@Core.Class
export default class SwingScript extends Core.Script {
//#region 相关变量定义
/**UI持有 */
private _seatUI: Seat;
/**触发器 */
private _trigger: Gameplay.Trigger;
/**交互器是否交互中,如果交互中让离开触发器事件失效(交互器bug有一定几率在交互时触发触发器离开事件) */
private _isInInteractive: boolean = false;
/**交互器 */
private _interactive: Gameplay.Interactor;
/**坐姿 */
@Core.Property({ displayName: "坐姿guid", group: "秋千设置" })
public sittingPositionGuid: string = "4175";
/**离开秋千位置 */
private _exitPosition: Type.Vector;
/**秋千旋转开始角度 */
@Core.Property({ displayName: "开始旋转角度", group: "秋千设置" })
public startRotation: Type.Rotation = new Type.Rotation(27, 0, 0)
/**秋千结束旋转角度 */
@Core.Property({ displayName: "结束旋转角度", group: "秋千设置" })
public endRotation: Type.Rotation = new Type.Rotation(-27, 0, 0)
/**秋千晃动一次用时 */
@Core.Property({ displayName: "旋转持续时时间 单位:秒", group: "秋千设置" })
public duration: number = 1;
/**秋千开始晃动延迟 */
@Core.Property({ displayName: "旋转延迟时间 单位:秒", group: "秋千设置" })
public delayTime: number = 1;
/**旋转动画Tween */
private _tween: Util.TweenUtil.Tween<Type.Rotation> = null;
//#endregion
//#region 相关事件定义
//#region 相关事件定义
private triggerOnEnter;
private triggerOnLeave;
private interaction;
private cancelInteraction;
private startSway;
private stopSway;
initAction() {
this.triggerOnEnter = (other: Core.GameObject) => {
if (other instanceof Gameplay.Character) {
if (this._seatUI == null) {
this._seatUI = UI.UIManager.instance.create(Seat);
}
UI.UIManager.instance.showUI(this._seatUI, UI.UILayerBottom, this.interaction, this.cancelInteraction);
}
}
this.triggerOnLeave = (other: Core.GameObject) => {
if (other instanceof Gameplay.Character) {
UI.UIManager.instance.hideUI(this._seatUI);
}
}
this.interaction = () => {
if (this._interactive.interactiveCharacter()) {
UI.UIManager.instance.hideUI(this._seatUI);
}
else {
this.startSway();
this._isInInteractive = true;
this._interactive.enterInteractiveState(Gameplay.getCurrentPlayer().character);
}
}
this.cancelInteraction = () => {
if (this._interactive.interactiveCharacter() === Gameplay.getCurrentPlayer().character) {
this.stopSway();
this._interactive.exitInteractiveState(this._exitPosition);
this._isInInteractive = false;
}
}
this.startSway = () => {
if (this._tween === null) {
/**设置初始值 */
this._tween = new Util.TweenUtil.Tween(this.startRotation.clone());
/**设置结束值与动画时间 */
this._tween.to(this.endRotation, this.duration * 1000);
/**设置运行逻辑 */
this._tween.onUpdate((rotation) => {
this.gameObject.relativeRotation = rotation;
})
/**设置变化曲线 */
this._tween.easing(Util.TweenUtil.Easing.Sinusoidal.InOut);
/**设置启动延迟时间 */
this._tween.delay(this.delayTime * 1000);
/**设置启动后关闭延迟时间 */
this._tween.onStart(() => {
this._tween.delay(0);
})
/**设置来回摇摆循环模式 */
this._tween.repeat(Infinity).yoyo(true);
/**设置结束逻辑 */
this._tween.onStop(() => {
this.gameObject.relativeRotation = Type.Rotation.zero;
this.useUpdate = false;
})
/**启动动画 */
this._tween.start();
this.useUpdate = true;
} else {
setTimeout(() => {
this._tween.start();
}, this.delayTime * 1000);
}
}
this.stopSway = () => {
this._tween.stop();
}
}
//#endregion
/** 当脚本被实例后,会在第一帧更新前调用此函数 */
protected async onStart(): Promise<void> {
if (Util.SystemUtil.isClient()) {
//加载秋千交互姿势
if (!Util.AssetUtil.isAssetExist(this.sittingPositionGuid)) {
await Util.AssetUtil.asyncDownloadAsset(this.sittingPositionGuid);
}
this.initAction();
this._trigger = this.gameObject.getChildByName("trigger") as Gameplay.Trigger;
this._interactive = this.gameObject.getChildByName("interaction") as Gameplay.Interactor;
let exitObj = (this.gameObject.getChildByName("exitPosition") as Core.GameObject);
this._exitPosition = exitObj.worldLocation
/**为触发器添加进入事件 */
this._trigger.onEnter.add(this.triggerOnEnter)
/**为触发器添加离开事件 */
this._trigger.onLeave.add(this.triggerOnLeave)
}
}
}
3.然后我们需要制作一个UI,当玩家进入秋千触发器时,UI显示并点击该UI后与秋千进行交互
制作UI并导出UI脚本
4.5
5
创建Seat脚本编写UI相应逻辑
5.5
/**
* AUTHOR: 疏影横斜水清浅
* TIME: 2023.02.22-10.20.05
*/
import seatUI_Generate from "./ui-generate/seatUI_generate";
export default class Seat extends seatUI_Generate {
/**点击坐下和起立的回调函数 */
private sitdown_onClick: Action = new Type.Action();
private standup_onClick: Action = new Type.Action();
/**计时器,避免连续点击 */
private _cd: number;
private _ConstCD = 0.5;
onStart() {
this.canUpdate = true;
this.btn_sitdown.onClicked.add(() => {
if (this._cd <= 0) {
this.sitdown_onClick.call();
this.btn_sitdown.visibility = UI.SlateVisibility.Hidden;
this.btn_standup.visibility = UI.SlateVisibility.Visible;
this._cd = this._ConstCD;
}
})
this.btn_standup.onClicked.add(() => {
if (this._cd <= 0) {
this.standup_onClick.call();
this.btn_sitdown.visibility = UI.SlateVisibility.Visible;
this.btn_standup.visibility = UI.SlateVisibility.Hidden;
this._cd = this._ConstCD;
}
})
}
onShow(sitdown_onClick: () => void, standup_onClick: () => void) {
this._cd = 0;
this.sitdown_onClick.clear();
this.sitdown_onClick.add(sitdown_onClick);
this.standup_onClick.clear();
this.standup_onClick.add(standup_onClick);
this.btn_sitdown.visibility = UI.SlateVisibility.Visible;
this.btn_standup.visibility = UI.SlateVisibility.Hidden;
}
onUpdate(dt: number) {
if (this._cd > 0) {
this._cd -= dt;
}
}
} 最后我们把写好的预制体脚本SwingScript拖上预制体对应位置保存即可
7
|