-- <* -- @Author: Saber -- @Description: 发行需求:全自由摄像机 -- *> CheatFreeCameraView = CheatFreeCameraView or BaseClass(BaseView) local CheatFreeCameraView = CheatFreeCameraView local math_random = math.random local Clamp = Mathf.Clamp function CheatFreeCameraView:__init() self.base_file = "cheat" self.layout_file = "CheatFreeCameraView" self.layer_name = "Top" self.destroy_imm = true self.use_background = false --全屏界面默认使用这个参数,非全屏界面自行设置 self.is_show = true self.mc_camera = nil -- 主摄像机组件 self.mc_trans = nil -- 主摄像机transform self.mc_node_trans = nil -- 主摄像机父节点transform self.mc_offset = Vector3(0, 0, 12) -- 主摄像机的节点内偏移 self.main_role = Scene.Instance:GetMainRole() -- 参数相关 self.view_mask_last_pos = Vector2(0, 0) -- 摄像机视角点击UV位置 self.view_asix_speed = 0.1 -- 摄像机轴移动速度 self.move_mask_start_pos = Vector2(0, 0) -- 摄像机移动起始点击UV位置 self.move_input = Vector2(0, 0) -- 摄像机自由移动输入方向 self.cam_move_speed = 0.2 -- 摄像机轴移动速度 self.cam_asix_radius = 50 -- 滑动移动轴半径 self.can_auto_round = false -- 是否可以自动环绕 self.auto_rotate_speed = 0 -- 自动环绕速度 self.camera_radius = 5 -- 摄像机定位半径 self.height_offset = 2 -- 摄像机Z轴offset self.show_main_canvas_flag = true -- 显示主界面canvas self.fixed_relative_camera_pos = nil -- 跟随移动时的相对摄像机位置 self.load_callback = function () self:LoadSuccess() self:AddEvent() end self.open_callback = function ( ) self:UpdateView() end self.destroy_callback = function ( ) self:DestroySuccess() end end function CheatFreeCameraView:Open( ) MainCamera.FreeCameraViewOpened = true BaseView.Open(self) end function CheatFreeCameraView:LoadSuccess() local nodes = { "free_camera_view_mask:obj", -- 全自动摄像机视角方向mask "free_camera_move_mask:obj", -- 全自动摄像机移动mask "closeBtn:obj", "hideBtn:obj", -- 自动操作按钮 "front_btn:obj", -- 主角正向 "back_btn:obj", -- 主角背面 "random_btn:obj", -- 主角随机环绕角度 "auto_round_btn:obj", -- 主角自动环绕 } self:GetChildren(nodes) -- 主摄FOV self.main_cam_fov_sl = self:GetChild("main_cam_fov/main_cam_fov_sl"):GetComponent("Slider") self.main_cam_fov_val = self:GetChild("main_cam_fov/main_cam_fov_val"):GetComponent(typeof(TMPro.TextMeshProUGUI)) -- 摄像机自动环绕速度 self.auto_round_sl = self:GetChild("auto_round/auto_round_sl"):GetComponent("Slider") self.auto_round_val = self:GetChild("auto_round/auto_round_val"):GetComponent(typeof(TMPro.TextMeshProUGUI)) -- 摄像机定位半径 self.radius_sl = self:GetChild("radius/radius_sl"):GetComponent("Slider") self.radius_val = self:GetChild("radius/radius_val"):GetComponent(typeof(TMPro.TextMeshProUGUI)) -- 摄像机Z轴offset self.height_offset_sl = self:GetChild("height_offset/height_offset_sl"):GetComponent("Slider") self.height_offset_val = self:GetChild("height_offset/height_offset_val"):GetComponent(typeof(TMPro.TextMeshProUGUI)) -- 全自由摄像机 self.free_camera_tog = self:GetChild("free_camera"):GetComponent("Toggle") -- 显示mainCanvas self.show_main_canvas_tog = self:GetChild("show_main_canvas"):GetComponent("Toggle") SetSizeDelta(self.free_camera_view_mask, ScreenWidth / 2, ScreenHeight) SetSizeDelta(self.free_camera_move_mask, ScreenWidth / 2, ScreenHeight) SetAnchoredPositionX(self.free_camera_move_mask, -366 - ScreenWidth / 2) SetAnchoredPosition(self.transform, -ClientConfig.iphone_x_offset_right, 0) end function CheatFreeCameraView:AddEvent() local function onOrientationChange() SetAnchoredPosition(self.transform, -ClientConfig.iphone_x_offset_right, 0) end self:BindEvent(GlobalEventSystem, EventName.ORIENTATION_DID_CHANGE, onOrientationChange) local function click_event(target) if target == self.closeBtn_obj then -- 关闭界面 local function ok( ... ) self:Close() end local ask_str = "(防止点错)是否确定关闭测试界面?" Alert.show(ask_str, Alert.Type.Two, ok, nil, "确定", "不不不我这是乱点的") elseif target == self.hideBtn_obj then -- 隐藏界面 self:HideAction(not self.is_show) elseif target == self.free_camera_tog.gameObject then -- 全自由摄像机,是则打开操作mask local isOn = self.free_camera_tog.isOn self.free_camera_move_mask_obj:SetActive(isOn) self.free_camera_view_mask_obj:SetActive(isOn) -- 如果使用全自由摄像机,那就要强制关闭自动环绕 self.can_auto_round = self.can_auto_round and not isOn elseif target == self.show_main_canvas_tog.gameObject then -- 是否显示主界面UI self.show_main_canvas_flag = self.show_main_canvas_tog.isOn self:ShowMainCanvas() elseif target == self.front_btn_obj then -- 摄像机朝向主角正面 -- 强制关闭自动环绕 self.can_auto_round = false self:SetCameraLookAtRoleFront() elseif target == self.back_btn_obj then -- 摄像机朝向主角背面 -- 强制关闭自动环绕 self.can_auto_round = false self:SetCameraLookAtRoleBack() elseif target == self.random_btn_obj then -- 摄像机随机角度于主角 -- 强制关闭自动环绕 self.can_auto_round = false self:SetCameraLookAtRoleWithRandomAngle() elseif target == self.auto_round_btn_obj then -- 摄像机自动环绕主角 self:SetCameraAutoRotateAroundRole() -- 自动环绕要关闭全自由摄像机 self.free_camera_tog.isOn = false self.free_camera_move_mask_obj:SetActive(false) self.free_camera_view_mask_obj:SetActive(false) end end AddClickEvent(self.closeBtn_obj, click_event) AddClickEvent(self.hideBtn_obj, click_event) AddClickEvent(self.free_camera_tog.gameObject, click_event) AddClickEvent(self.show_main_canvas_tog.gameObject, click_event) AddClickEvent(self.front_btn_obj, click_event) AddClickEvent(self.back_btn_obj, click_event) AddClickEvent(self.random_btn_obj, click_event) AddClickEvent(self.auto_round_btn_obj, click_event) local function onSliderDrag(target) local value = target:GetComponent("Slider").value if target == self.main_cam_fov_sl.gameObject then self.main_cam_fov_val.text = value if self.mc_camera then self.mc_camera.fieldOfView = value end elseif target == self.auto_round_sl.gameObject then self.auto_round_val.text = tonumber(string.format("%.2f", value)) self.auto_rotate_speed = value elseif target == self.radius_sl.gameObject then self.radius_val.text = tonumber(string.format("%.2f", value)) self.camera_radius = value elseif target == self.height_offset_sl.gameObject then -- z轴offset self.height_offset_val.text = tonumber(string.format("%.2f", value)) self.height_offset = value end end AddDragEvent(self.main_cam_fov_sl.gameObject, onSliderDrag) AddDragEvent(self.auto_round_sl.gameObject, onSliderDrag) AddDragEvent(self.radius_sl.gameObject, onSliderDrag) AddDragEvent(self.height_offset_sl.gameObject, onSliderDrag) -- 全自由摄像机转动 local function onPressViewMask(target, x, y) self.view_mask_last_pos = Vector2(x, y) end local function onDragViewMask(target, x, y) local pos_offset_x = x - self.view_mask_last_pos.x local pos_offset_y = y - self.view_mask_last_pos.y local angel_delta = Vector2(-pos_offset_y * self.view_asix_speed, pos_offset_x * self.view_asix_speed) local cam_angel = self:GetCameraYEulerAngle() local new_angle = Vector3(cam_angel.x + angel_delta.x, cam_angel.y + angel_delta.y, cam_angel.z) self:SetCameraYEulerAngle(new_angle) self.view_mask_last_pos = Vector2(x, y) end local function onExitViewMask(target) self.view_mask_last_pos = Vector2(0, 0) end AddDragBeginEvent(self.free_camera_view_mask_obj, onPressViewMask) AddDragEvent(self.free_camera_view_mask_obj, onDragViewMask) AddDragEndEvent(self.free_camera_view_mask_obj, onExitViewMask) -- 全自由摄像机移动 local function onPressMoveMask(target, x, y) self.move_mask_start_pos = Vector2(x, y) end local function onDragMoveMask(target, x, y) local pos_offset_x = x - self.move_mask_start_pos.x local pos_offset_y = y - self.move_mask_start_pos.y local input = Vector2(pos_offset_x, pos_offset_y) / self.cam_asix_radius input.x = Clamp(input.x, -1, 1) input.y = Clamp(input.y, -1, 1) self.move_input = input end local function onExitMoveMask(target) self.move_mask_start_pos = Vector2(0, 0) self.move_input = Vector2(0, 0) end AddDragBeginEvent(self.free_camera_move_mask_obj, onPressMoveMask) AddDragEvent(self.free_camera_move_mask_obj, onDragMoveMask) AddDragEndEvent(self.free_camera_move_mask_obj, onExitMoveMask) end function CheatFreeCameraView:UpdateView() self:GetMainCamera() self:InitOptionsData() self:HideAction(true) self:BindCameraMoveEvent() self:ShowMainCanvas() end -- 获取主摄像机 function CheatFreeCameraView:GetMainCamera( ) -- 获取摄像机 if not self.mc_camera or not self.mc_trans or not self.mc_node_trans then self.mc_camera = MainCamera.Instance.camera self.mc_trans = MainCamera.Instance.camera_gameObject.transform self.mc_node_trans = MainCamera.Instance.transform end end -- 初始化设置选项 function CheatFreeCameraView:InitOptionsData( ) self.main_cam_fov_sl.value = self.mc_camera.fieldOfView self.main_cam_fov_val.text = self.mc_camera.fieldOfView self.main_camera_fov = self.mc_camera.fieldOfView -- 用于复原摄像机 self.auto_round_sl.value = self.auto_rotate_speed self.auto_round_val.text = self.auto_rotate_speed self.radius_sl.value = self.camera_radius self.radius_val.text = self.camera_radius self.height_offset_sl.value = self.height_offset self.height_offset_val.text = self.height_offset self.show_main_canvas_tog.isOn = self.show_main_canvas_flag end -- 获取主角当前真实世界坐标 function CheatFreeCameraView:GetMainRoleRealWorldPos( ) return self.main_role.modelObj_transform.position + Vector3(0, self.height_offset, 0) end function CheatFreeCameraView:GetMainRoleForwardDir( ) return self.main_role.modelObj_transform.forward end function CheatFreeCameraView:GetMainRoleUpDir( ) return self.main_role.modelObj_transform.up end function CheatFreeCameraView:GetCameraYEulerAngle( ) return self.mc_trans.eulerAngles end function CheatFreeCameraView:SetCameraYEulerAngle(val) self.mc_trans.rotation = Quaternion.Euler(val) end function CheatFreeCameraView:GetCameraForwardDir( ) return self.mc_trans.forward end function CheatFreeCameraView:GetCameraRightDir( ) return self.mc_trans.right end function CheatFreeCameraView:GetCameraNodePosition( ) return self.mc_node_trans.position end function CheatFreeCameraView:SetCameraNodePosition(val) self.mc_node_trans.position = val end -- 摄像机位置按钮相关 -- 摄像机朝向主角正面 function CheatFreeCameraView:SetCameraLookAtRoleFront( ) local role_pos = self:GetMainRoleRealWorldPos() local role_forward = self:GetMainRoleForwardDir() local camera_pos = role_forward * self.camera_radius + role_pos + self.mc_offset if self.mc_node_trans and self.mc_trans then self.mc_node_trans.position = camera_pos self.mc_trans:LookAt(role_pos) end end -- 摄像机朝向主角背面 function CheatFreeCameraView:SetCameraLookAtRoleBack( ) local role_pos = self:GetMainRoleRealWorldPos() local role_forward = self:GetMainRoleForwardDir() local camera_pos = - role_forward * self.camera_radius + role_pos + self.mc_offset if self.mc_node_trans and self.mc_trans then self.mc_node_trans.position = camera_pos self.mc_trans:LookAt(role_pos) end end -- 摄像机随机角度于主角 function CheatFreeCameraView:SetCameraLookAtRoleWithRandomAngle( ) local role_pos = self:GetMainRoleRealWorldPos() local role_forward = self:GetMainRoleForwardDir() local role_up = self:GetMainRoleUpDir() local random_angle = math_random(-180, 180) local camera_pos = Quaternion.AngleAxis(random_angle, role_up) * role_forward * self.camera_radius + role_pos + self.mc_offset if self.mc_node_trans and self.mc_trans then self.mc_node_trans.position = camera_pos self.mc_trans:LookAt(role_pos) end end -- 摄像机自动环绕主角 function CheatFreeCameraView:SetCameraAutoRotateAroundRole( ) self.can_auto_round = true self.last_node_time = Status.NowTime local start_angle = 0 if not self.auto_rotate_camera_id then local function auto_rotate() if self.can_auto_round then local role_pos = self:GetMainRoleRealWorldPos() local role_forward = self:GetMainRoleForwardDir() local role_up = self:GetMainRoleUpDir() local past_time = Status.NowTime - self.last_node_time local speed_per_frame = self.auto_rotate_speed / 30 start_angle = start_angle + speed_per_frame * past_time / 0.02 local camera_pos = Quaternion.AngleAxis(start_angle, role_up) * role_forward * self.camera_radius + role_pos + self.mc_offset if self.mc_node_trans and self.mc_trans then self.mc_node_trans.position = camera_pos self.mc_trans:LookAt(role_pos) end end self.last_node_time = Status.NowTime end self.auto_rotate_camera_id = GlobalTimerQuest:AddPeriodQuest(auto_rotate, 0.02, -1) end end function CheatFreeCameraView:HideAction(show) self:StopHideAction() self.is_show = show self.hideBtn.transform.localRotation = Quaternion.Euler(Vector3(0, 0, self.is_show and 90 or 270)) local target_pos_x = (self.is_show and 0 or 366 ) - ClientConfig.iphone_x_offset_right self.con_anim_id = TweenLite.to(self, self.transform, TweenLite.UiAnimationType.ANCHORED_POSX, target_pos_x, 0.3, nil, TweenFunc.EASE_OUT_QUINT) end function CheatFreeCameraView:StopHideAction( ) if self.con_anim_id then TweenLite.Stop(self.con_anim_id) SetAnchoredPositionX(self.transform, (self.is_show and 0 or 366) - ClientConfig.iphone_x_offset_right) end end function CheatFreeCameraView:BindCameraMoveEvent( ) if not self.camera_move_event_id then local function camera_move_func() if self.free_camera_tog.isOn then self.fixed_relative_camera_pos = nil if self.move_input.x ~= 0 or self.move_input.y ~= 0 then local input = self.move_input local forward_dir = self:GetCameraForwardDir() local right_dir = self:GetCameraRightDir() local cur_pos = self:GetCameraNodePosition() local new_pos = cur_pos + forward_dir * input.y * self.cam_move_speed + right_dir * input.x * self.cam_move_speed self:SetCameraNodePosition(new_pos) end else if not self.fixed_relative_camera_pos then self.fixed_relative_camera_pos = self:GetCameraNodePosition() - self:GetMainRoleRealWorldPos() end self:SetCameraNodePosition(self:GetMainRoleRealWorldPos() + self.fixed_relative_camera_pos) end end self.camera_move_event_id = GlobalTimerQuest:AddPeriodQuest(camera_move_func, 0.02, -1) end end function CheatFreeCameraView:ShowMainCanvas( ) panelMgr:GetParent("Main").gameObject:SetActive(self.show_main_canvas_flag) panelMgr:GetParent("NameBoard").gameObject:SetActive(self.show_main_canvas_flag) panelMgr:GetParent("Dynamic_NameBoard").gameObject:SetActive(self.show_main_canvas_flag) end function CheatFreeCameraView:DestroySuccess( ) self:StopHideAction() if self.auto_rotate_camera_id then GlobalTimerQuest:CancelQuest(self.auto_rotate_camera_id) self.auto_rotate_camera_id = nil end if self.camera_move_event_id then GlobalTimerQuest:CancelQuest(self.camera_move_event_id) self.camera_move_event_id = nil end -- 复原摄像机 if self.mc_camera then self.mc_camera.fieldOfView = self.main_camera_fov end self.mc_trans.localRotation = Quaternion.Euler(SceneCameraRotate,0,0) MainCamera.FreeCameraViewOpened = false end