UNPKG

@puerts/cli

Version:

PureTS is a quick scaffold tool, which can be used in the project.

310 lines (285 loc) 16.4 kB
import ue = CS.UnityEngine; // 是用来协助进行类型检查和声明的,在运行时是完全不存在 import Ticker from './Core/Ticker'; const { GameObject, Time, Vector2, Vector3, RenderMode, Camera, Canvas, CanvasRenderer, MeshFilter, Mesh, MeshRenderer, Light, LightType, FontStyle, Quaternion, UI, CameraClearFlags, Resources, EventSystems, RectTransform, TextAnchor, LightmapBakeType} = CS.UnityEngine; const {CanvasScaler,Slider} = CS.UnityEngine.UI; const {$typeof} = puer; namespace Game { interface GameOption { /** 每秒最大渲染帧数限制 */ maxFps?:number, /**是否为线上*/ online?:boolean } interface GameObj { object:ue.GameObject, components?:{ camera?:ue.Camera, canvas?:ue.Canvas, canvaslScale?:ue.UI.CanvasScaler, graphicRaycaster?:ue.UI.GraphicRaycaster eventSystem?:ue.EventSystems.EventSystem, standaloneInputModule?:ue.EventSystems.StandaloneInputModule, text?:ue.UI.Text, rectTransform?:ue.RectTransform, slider?:ue.UI.Slider } } interface RandomizeMatrix { position:[number,number,number], scale:[number,number,number], rotaion:[number,number,number] } export class App{ private _maxFps:number; // 最大帧 private ticker:Ticker; // 轮循执行器 public static mainCamera:ue.GameObject; // 主相机 public static uiCamera:ue.GameObject; // Ui相机 public static uiCanvas:ue.GameObject; // Ui画布 public static eventSystem:ue.GameObject; // Ui事件系统 public static stage:ue.GameObject; // 舞台节点 private cubeList:ue.GameObject[] = []; // 保存 Cube 列表 private cubeCont:number = 100; // 记录 Cube 数量 private speed:number = 1; // 记录 Cube 速度 /** * 构造方法 * @param option 游戏启动参数 */ constructor(option?:GameOption){ if(option){ for(let key in option){ this[key] = option[key]; }; }; if(!this.maxFps){ this.maxFps = 60; }; if(!this.maxFps){ this.maxFps = 60; }; this.ticker = new Ticker(this.maxFps); } /** * 应用启动入口 */ async init():Promise<void>{ this.ticker.start(); // 启动轮循执行器 const mainCameraObj = this.createMainCamera(); App.mainCamera = mainCameraObj.object; // 创建主相机 const uiCameraObj = this.createUiCamera(); App.uiCamera = uiCameraObj.object; // 创建UI相机 const canvasObj = this.createCanas(uiCameraObj.components.camera); App.uiCanvas = canvasObj.object; // 创建UI画布 const eventSystemObj = this.createEventSystem(); App.eventSystem = eventSystemObj.object; // 创建UI事件系统 App.stage = new GameObject("Stage"); // 创建舞台,内容全在舞台上 const speedTextObj = this.createUiText('TextSpeed'); // 速度文本 const countTextObj = this.createUiText('TextCount'); // 数量文本 countTextObj.components.rectTransform.anchoredPosition = new Vector2(0,-40); // 调整显示位置稍微向下偏移一点 const timers = {}; // 用于保存计时器,防抖之用 const updateSpeed = (val:number)=>{ // 更新速度方法 this.speed = val; speedTextObj.components.text.text = `Speed:${val.toFixed(3)}` }; updateSpeed(this.speed); // 速度首次初始化 const updateCount = (val:number)=>{ // 更新数量方法 val = ~~val; // 取整 if(val === this.cubeList.length){return;}; // 值与当前列表的数量一样则无需处理 this.cubeCont = val; // 记录最新数量 countTextObj.components.text.text = `Count:${this.cubeCont}`; // 更新提示文字 clearTimeout(timers['updateCount']); // 防抖处理 timers['updateCount'] = setTimeout(() => { // 防抖处理 this.cubeList = this.createCubeList(); }, 200); }; updateCount(this.cubeCont); // 数量首次初始化 const speedSlideObj = this.createUiSlider('SliderSpeed',updateSpeed); // 创建调节速度的Slide speedSlideObj.components.slider.minValue = this.speed; // 最小值为默认初始值 speedSlideObj.components.slider.maxValue = this.speed + 100 - this.speed; // 最大值100 const countSlideObj = this.createUiSlider('SliderCount',updateCount); // 创建调节数量的Slide countSlideObj.components.rectTransform.anchoredPosition = new Vector2(0,80); // 调整显示位置稍微向下偏移一点 countSlideObj.components.slider.minValue = this.cubeCont; // 最小值为默认初始值 countSlideObj.components.slider.maxValue = this.cubeCont + 20000 - this.cubeCont; // 最大值3000 const update = (deltaTime:number,performance:number)=>{ // 更新方法(当热重载开启时,修改该方法即时生效) for(let i=0,len=this.cubeList.length; i<len; i++){ const cube = this.cubeList[i]; const r = Vector3.op_Multiply(new Vector3(1,1,0), deltaTime / 100 * this.speed); cube.transform.Rotate(r); }; }; Ticker.add(update); // 添加轮循执行方法,这里的 deltaTime 为 ms(实际生产中不建议这么写,update 可以放在对象上也同样能实现热重载) } /** * 创建 Text Ui * @param name string 对象名称 * @returns GameObj */ createUiText(name:string):GameObj{ const object:ue.GameObject = new GameObject(name); object.transform.SetParent(App.uiCanvas.transform,false); object.AddComponent($typeof(CanvasRenderer)); const text:ue.UI.Text = object.AddComponent($typeof(UI.Text)) as ue.UI.Text; text.font = Resources.Load("Fonts/Arial") as ue.Font; text.alignment = TextAnchor.MiddleCenter; text.fontSize = 24; text.fontStyle = FontStyle.Bold; // text.text = `${speed}`; const rectTransform:ue.RectTransform = object.GetComponent($typeof(RectTransform)) as ue.RectTransform; rectTransform.localPosition = new Vector3(0,423,0); rectTransform.anchorMin = new Vector2(0,1); rectTransform.anchorMax = new Vector2(1,1); rectTransform.anchoredPosition = new Vector2(0,0); rectTransform.sizeDelta = new Vector2(0,120); rectTransform.pivot = new Vector2(0.5,1); return {object,components:{text,rectTransform}}; } /** * 创建 Slider Ui * @param name string 对象名称 * @param call function Ui事件触发方法 * @returns GameObj */ createUiSlider(name:string,call:ue.Events.UnityAction$1<number>):GameObj{ const object:ue.GameObject = GameObject.Instantiate(Resources.Load("Prefabs/Slider")) as ue.GameObject; object.name = name; const rectTransform:ue.RectTransform = object.GetComponent($typeof(RectTransform)) as ue.RectTransform; const slider:ue.UI.Slider = object.GetComponent($typeof(Slider)) as ue.UI.Slider; slider.minValue = 1; slider.maxValue = 10; // slider.wholeNumbers = true; slider.onValueChanged.AddListener(call); // 为 UI 添加事件绑定 rectTransform.transform.localPosition = new Vector3(0,160,0); rectTransform.transform.localScale = new Vector3(2,2,2); rectTransform.sizeDelta = new Vector2(120,20); object.transform.SetParent(App.uiCanvas.transform,false); return {object,components:{slider,rectTransform}}; } /** * 创建随机矩阵 * @returns RandomizeMatrix */ createRandomizeMatrix():RandomizeMatrix{ const position:RandomizeMatrix['position'] = [ Math.random() * 20 - 10, Math.random() * 20 - 10, Math.random() * 20 - 10, ]; const scaleVal = Math.random() * 1; const scale:RandomizeMatrix['scale'] = [scaleVal,scaleVal,scaleVal]; const rotaion:RandomizeMatrix['rotaion'] = [ Math.random() * 90 * Math.PI, Math.random() * 90 * Math.PI, Math.random() * 90 * Math.PI ]; return {position,scale,rotaion}; } /** * 创建Cube列表 * @returns ue.GameObject[] */ createCubeList():ue.GameObject[]{ for(let i=0,len=this.cubeList.length; i<len; i++){ // 销毁已有的 GameObject.Destroy(this.cubeList[i]); // CS.UnityEngine.Object.DestroyImmediate(this.cubeList[i]); }; const result:ue.GameObject[] = []; for(let i=0; i<this.cubeCont; i++){ const cube:ue.GameObject = this.createCube(`Cube${i}`); result.push(cube); }; return result; } /** * 创建Cube * @param name string cube名称 * @returns ue.GameObject */ createCube(name:string):ue.GameObject{ const object:ue.GameObject = new GameObject(name); object.transform.SetParent(App.stage.transform); const cube_mf:ue.MeshFilter = object.AddComponent($typeof(MeshFilter)) as ue.MeshFilter; cube_mf.mesh = Resources.GetBuiltinResource($typeof(Mesh),"Cube.fbx") as ue.Mesh; const cube_mr:ue.MeshRenderer = object.AddComponent($typeof(MeshRenderer)) as ue.MeshRenderer; const cube_t = Resources.Load("Textures/PuertsLogo") as ue.Texture; cube_mr.material.SetFloat('_Metallic',0.8); cube_mr.material.SetFloat('_Glossiness',0.78); cube_mr.material.SetTexture('_MainTex',cube_t); const randomizeMatrix = this.createRandomizeMatrix(); object.transform.localPosition = new Vector3(...randomizeMatrix.position); object.transform.localRotation = Quaternion.Euler(...randomizeMatrix.rotaion); // object.transform.localScale = new Vector3(...randomizeMatrix.scale); object.transform.SetParent(App.stage.transform); return object; } set maxFps(val:number){ this._maxFps = val; } get maxFps():number{ return this._maxFps; } /** * 创建主相机 * @returns ue.GameObject */ createMainCamera():GameObj{ const object:ue.GameObject = new GameObject("Main Camera"); let camera:ue.Camera = object.AddComponent($typeof(Camera)) as ue.Camera; camera.clearFlags = CameraClearFlags.Skybox; camera.cullingMask = ~(1 << 5); // 主相机渲染除UI的所有层(https://gameinstitute.qq.com/community/detail/126782) camera.nearClipPlane = 2; camera.farClipPlane = 40; camera.transform.Rotate(20,0,0); camera.transform.localScale = new Vector3(0.5,0.5,0.5); camera.transform.localPosition = new Vector3(0,7,-20); return {object,components:{camera}}; } /** * 创建UI相机 * @returns object */ createUiCamera():GameObj{ const object:ue.GameObject = new GameObject("Ui Camera"); object.transform.position = new Vector3(-10,0,0); const camera:ue.Camera = object.AddComponent($typeof(Camera)) as ue.Camera; camera.clearFlags = CameraClearFlags.Depth; camera.cullingMask = 1 << 5; // UI相机仅渲染UI层 camera.orthographic = true; camera.nearClipPlane = 5; camera.farClipPlane = 15; return {object,components:{camera}}; } /** * 创建Ui画布 */ createCanas(cameraComponent:ue.Camera):GameObj{ const object:ue.GameObject = new GameObject("Canvas"); object.layer = 5; // 设置属于UI层 const canvas:ue.Canvas = object.AddComponent($typeof(Canvas)) as ue.Canvas; canvas.renderMode = RenderMode.ScreenSpaceCamera; canvas.worldCamera = cameraComponent; canvas.planeDistance = 10; const canvaslScale:ue.UI.CanvasScaler = object.AddComponent($typeof(CanvasScaler)) as ue.UI.CanvasScaler; canvaslScale.uiScaleMode = CanvasScaler.ScaleMode.ScaleWithScreenSize; canvaslScale.referenceResolution = new Vector2(428,926); canvaslScale.matchWidthOrHeight = 1; const graphicRaycaster = object.AddComponent($typeof(UI.GraphicRaycaster)) as ue.UI.GraphicRaycaster; return {object,components:{canvas,canvaslScale,graphicRaycaster}}; } /** * 创建UI事件系统 * @returns object */ createEventSystem():GameObj{ const object:ue.GameObject = new GameObject("EventSystem"); const eventSystem = object.AddComponent($typeof(EventSystems.EventSystem)) as ue.EventSystems.EventSystem; const standaloneInputModule = object.AddComponent($typeof(EventSystems.StandaloneInputModule)) as ue.EventSystems.StandaloneInputModule; return {object,components:{eventSystem,standaloneInputModule}}; } } } (()=>{ const app = new Game.App({maxFps:60,online:false}); app.init(); })() export default Game.App;