[预制体] 【预制体】如何制作一个丝滑的秋千-单机版

[复制链接]
1087 |2
疏影横斜水清浅 发表于 2023-2-22 12:04:15 | 显示全部楼层 |阅读模式
话不多说,先让我们一起看看最终结果演示

那么接下来让我们从零开始制作该秋千预制体
1.首先创建一个预制体命名为swing,拖入对应的模型、触发器、交互物、空锚点

1

1

2

2

3

3

2.接着创建预制体脚本

4

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

4.5

5

5

创建Seat脚本编写UI相应逻辑

5.5

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

7


6

6
回复

使用道具 举报

逝水无痕 发表于 2023-2-22 14:10:04 | 显示全部楼层
牛!!!
回复

使用道具 举报

唯美傷飛上天 发表于 2023-2-24 16:12:58 | 显示全部楼层
这不打包个项目让孩子学习一下
回复

使用道具 举报

热门版块
快速回复 返回顶部 返回列表