perf: 支持相机运镜
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,4 @@
|
|||||||
import { _decorator, Component, Node, Vec3, Camera, view } from 'cc';
|
import { _decorator, Component, Node, Vec3, Camera, view, find } from 'cc';
|
||||||
const { ccclass, property } = _decorator;
|
const { ccclass, property } = _decorator;
|
||||||
|
|
||||||
@ccclass('CameraFollow')
|
@ccclass('CameraFollow')
|
||||||
@@ -22,84 +22,145 @@ export class CameraFollow extends Component {
|
|||||||
@property
|
@property
|
||||||
mapHeight: number = 1920; // 地图高度
|
mapHeight: number = 1920; // 地图高度
|
||||||
|
|
||||||
|
|
||||||
|
@property
|
||||||
|
initialFocusNodeName: string = 'guai_10';
|
||||||
|
|
||||||
|
@property
|
||||||
|
initialFocusDuration: number = 2.0;
|
||||||
|
|
||||||
private camera: Camera | null = null;
|
private camera: Camera | null = null;
|
||||||
|
private readonly _targetPosition: Vec3 = new Vec3();
|
||||||
|
private readonly _desiredPosition: Vec3 = new Vec3();
|
||||||
|
private readonly _newPosition: Vec3 = new Vec3();
|
||||||
|
private initialFocusNode: Node | null = null;
|
||||||
|
private initialFocusTimer = 0;
|
||||||
|
private isInitialFocusActive = false;
|
||||||
|
|
||||||
onLoad() {
|
onLoad() {
|
||||||
// 获取相机组件
|
// 获取相机组件
|
||||||
this.camera = this.getComponent(Camera);
|
this.camera = this.getComponent(Camera);
|
||||||
|
|
||||||
this.camera.orthoHeight = 680
|
|
||||||
if (!this.camera) {
|
if (!this.camera) {
|
||||||
console.error('CameraFollow: 未找到Camera组件');
|
console.error('CameraFollow: 未找到Camera组件');
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
// 根据项目需要调整初始正交高度
|
||||||
|
this.camera.orthoHeight = 550;
|
||||||
}
|
}
|
||||||
|
|
||||||
start() {
|
start() {
|
||||||
if (this.target) {
|
const hasInitialFocus = this.beginInitialFocus();
|
||||||
// 初始化相机位置
|
|
||||||
const initialPos = this.target.position.clone();
|
if (!hasInitialFocus && this.target) {
|
||||||
initialPos.add(this.offset);
|
this.snapToNode(this.target);
|
||||||
this.node.position = initialPos;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
update(deltaTime: number) {
|
update(deltaTime: number) {
|
||||||
|
if (this.isInitialFocusActive) {
|
||||||
|
if (this.initialFocusNode) {
|
||||||
|
this.snapToNode(this.initialFocusNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.initialFocusTimer -= deltaTime;
|
||||||
|
if (this.initialFocusTimer > 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.isInitialFocusActive = false;
|
||||||
|
}
|
||||||
|
|
||||||
if (!this.target) return;
|
if (!this.target) return;
|
||||||
|
|
||||||
// 计算目标位置
|
this.target.getPosition(this._targetPosition);
|
||||||
const targetPosition = this.target.position.clone();
|
Vec3.add(this._desiredPosition, this._targetPosition, this.offset);
|
||||||
targetPosition.add(this.offset);
|
|
||||||
|
|
||||||
// 应用地图边界限制
|
// 应用地图边界限制
|
||||||
const clampedPosition = this.clampCameraPosition(targetPosition);
|
const clampedPosition = this.clampCameraPosition(this._desiredPosition);
|
||||||
|
|
||||||
// 使用插值实现平滑跟随
|
// 使用插值实现平滑跟随
|
||||||
const currentPosition = this.node.position;
|
const currentPosition = this.node.position;
|
||||||
const newPosition = new Vec3();
|
const lerpFactor = this.computeLerpFactor(deltaTime);
|
||||||
|
|
||||||
// 根据平滑度设置插值速度
|
if (lerpFactor >= 1) {
|
||||||
const lerpFactor = Math.min(1.0, this.followSpeed * deltaTime * (1 - this.smoothness + 0.1));
|
this.node.setPosition(clampedPosition);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Vec3.lerp(newPosition, currentPosition, clampedPosition, lerpFactor);
|
Vec3.lerp(this._newPosition, currentPosition, clampedPosition, lerpFactor);
|
||||||
this.node.position = newPosition;
|
this.node.setPosition(this._newPosition);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 限制相机位置在地图边界内
|
// 限制相机位置在地图边界内
|
||||||
private clampCameraPosition(position: Vec3): Vec3 {
|
private clampCameraPosition(position: Vec3): Vec3 {
|
||||||
if (!this.camera) return position;
|
if (!this.camera) return position.clone();
|
||||||
|
|
||||||
// 获取屏幕可见区域大小
|
// 获取屏幕可见区域大小
|
||||||
const visibleSize = view.getVisibleSize();
|
const visibleSize = view.getVisibleSize();
|
||||||
|
const aspectRatio = visibleSize.height > 0 ? visibleSize.width / visibleSize.height : 1;
|
||||||
|
|
||||||
// 计算相机能看到的世界区域的一半
|
// 计算相机能看到的世界区域的一半(正交相机)。缩放后需要除以 zoomRatio。
|
||||||
const halfCameraWidth = visibleSize.width * 0.5;
|
const cameraWithZoom = this.camera as Camera & { zoomRatio?: number };
|
||||||
const halfCameraHeight = visibleSize.height * 0.5;
|
const zoomRatio = cameraWithZoom.zoomRatio ?? 1;
|
||||||
|
const halfCameraHeight = this.camera.orthoHeight / Math.max(zoomRatio, 0.0001);
|
||||||
|
const halfCameraWidth = halfCameraHeight * aspectRatio;
|
||||||
|
|
||||||
// 计算地图边界(地图锚点为0.5,0.5,所以范围是-mapWidth/2到+mapWidth/2)
|
|
||||||
const mapHalfWidth = this.mapWidth * 0.5;
|
const mapHalfWidth = this.mapWidth * 0.5;
|
||||||
const mapHalfHeight = this.mapHeight * 0.5;
|
const mapHalfHeight = this.mapHeight * 0.5;
|
||||||
|
|
||||||
// 计算相机位置的边界(确保相机边缘不超出地图边界)
|
|
||||||
const minX = -mapHalfWidth + halfCameraWidth;
|
|
||||||
const maxX = mapHalfWidth - halfCameraWidth;
|
|
||||||
const minY = -mapHalfHeight + halfCameraHeight;
|
|
||||||
const maxY = mapHalfHeight - halfCameraHeight;
|
|
||||||
|
|
||||||
// 限制相机位置
|
|
||||||
const clampedPosition = position.clone();
|
const clampedPosition = position.clone();
|
||||||
clampedPosition.x = Math.max(minX, Math.min(maxX, position.x));
|
|
||||||
clampedPosition.y = Math.max(minY, Math.min(maxY, position.y));
|
if (mapHalfWidth <= halfCameraWidth) {
|
||||||
|
// 地图宽度不足以填满视野,水平居中
|
||||||
|
clampedPosition.x = 0;
|
||||||
|
} else {
|
||||||
|
const minX = -mapHalfWidth + halfCameraWidth;
|
||||||
|
const maxX = mapHalfWidth - halfCameraWidth;
|
||||||
|
clampedPosition.x = Math.max(minX, Math.min(maxX, clampedPosition.x));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mapHalfHeight <= halfCameraHeight) {
|
||||||
|
// 地图高度不足以填满视野,垂直居中
|
||||||
|
clampedPosition.y = 0;
|
||||||
|
} else {
|
||||||
|
const minY = -mapHalfHeight + halfCameraHeight;
|
||||||
|
const maxY = mapHalfHeight - halfCameraHeight;
|
||||||
|
clampedPosition.y = Math.max(minY, Math.min(maxY, clampedPosition.y));
|
||||||
|
}
|
||||||
|
|
||||||
return clampedPosition;
|
return clampedPosition;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private computeLerpFactor(deltaTime: number): number {
|
||||||
|
if (deltaTime <= 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const speed = Math.max(0, this.followSpeed);
|
||||||
|
if (speed <= 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.smoothness <= 0) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const smooth = Math.min(this.smoothness, 0.9999);
|
||||||
|
const followRate = speed * (1 - smooth);
|
||||||
|
if (followRate <= 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const lerpFactor = 1 - Math.exp(-followRate * deltaTime);
|
||||||
|
return Math.min(1, Math.max(0, lerpFactor));
|
||||||
|
}
|
||||||
|
|
||||||
// 设置跟随目标
|
// 设置跟随目标
|
||||||
setTarget(target: Node) {
|
setTarget(target: Node) {
|
||||||
this.target = target;
|
this.target = target;
|
||||||
if (target) {
|
if (target && !this.isInitialFocusActive) {
|
||||||
const initialPos = target.position.clone();
|
this.snapToNode(target);
|
||||||
initialPos.add(this.offset);
|
|
||||||
this.node.position = initialPos;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -112,9 +173,58 @@ export class CameraFollow extends Component {
|
|||||||
snapToTarget() {
|
snapToTarget() {
|
||||||
if (!this.target) return;
|
if (!this.target) return;
|
||||||
|
|
||||||
const targetPosition = this.target.position.clone();
|
this.snapToNode(this.target);
|
||||||
targetPosition.add(this.offset);
|
}
|
||||||
const clampedPosition = this.clampCameraPosition(targetPosition);
|
|
||||||
this.node.position = clampedPosition;
|
private beginInitialFocus(): boolean {
|
||||||
|
if (this.initialFocusDuration <= 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
let focusNode = this.initialFocusNode;
|
||||||
|
|
||||||
|
if (!focusNode) {
|
||||||
|
const scene = this.node.scene;
|
||||||
|
if (!scene) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.initialFocusNodeName) {
|
||||||
|
focusNode = find(this.initialFocusNodeName, scene) ?? this.findNodeByName(scene, this.initialFocusNodeName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!focusNode) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.initialFocusNode = focusNode;
|
||||||
|
this.initialFocusTimer = this.initialFocusDuration;
|
||||||
|
this.isInitialFocusActive = true;
|
||||||
|
this.snapToNode(focusNode);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private snapToNode(node: Node) {
|
||||||
|
node.getPosition(this._targetPosition);
|
||||||
|
Vec3.add(this._desiredPosition, this._targetPosition, this.offset);
|
||||||
|
const clamped = this.clampCameraPosition(this._desiredPosition);
|
||||||
|
this.node.setPosition(clamped);
|
||||||
|
}
|
||||||
|
|
||||||
|
private findNodeByName(root: Node, name: string): Node | null {
|
||||||
|
if (root.name === name) {
|
||||||
|
return root;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i = 0; i < root.children.length; i++) {
|
||||||
|
const child = root.children[i];
|
||||||
|
const match = this.findNodeByName(child, name);
|
||||||
|
if (match) {
|
||||||
|
return match;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import { _decorator, Component, Node, Vec3, input, Input, EventTouch, Camera, view, tween, Animation, Collider2D, Contact2DType, Label, Color, Canvas, UITransform, AudioSource } from 'cc';
|
import { _decorator, Component, Node, Vec3, input, Input, EventTouch, Camera, view, tween, Animation, Collider2D, Contact2DType, Label, Color, Canvas, UITransform, AudioSource, Sprite } from 'cc';
|
||||||
import { TiledMapPathfinder } from './TiledMapPathfinder';
|
import { TiledMapPathfinder } from './TiledMapPathfinder';
|
||||||
const { ccclass, property } = _decorator;
|
const { ccclass, property } = _decorator;
|
||||||
|
|
||||||
@@ -13,6 +13,9 @@ export class PlayerController extends Component {
|
|||||||
@property(Node)
|
@property(Node)
|
||||||
bonus: Node | null = null;
|
bonus: Node | null = null;
|
||||||
|
|
||||||
|
@property(Node)
|
||||||
|
bonusWuqi: Node | null = null;
|
||||||
|
|
||||||
@property(Camera)
|
@property(Camera)
|
||||||
camera: Camera | null = null; // 主摄像机
|
camera: Camera | null = null; // 主摄像机
|
||||||
|
|
||||||
@@ -49,6 +52,9 @@ export class PlayerController extends Component {
|
|||||||
private props: Node[] = [];
|
private props: Node[] = [];
|
||||||
|
|
||||||
private guideNode: Node | null = null;
|
private guideNode: Node | null = null;
|
||||||
|
private activePopup: Node | null = null;
|
||||||
|
private activePopupName: string | null = null;
|
||||||
|
private pendingPopupHide: (() => void) | null = null;
|
||||||
|
|
||||||
onLoad() {
|
onLoad() {
|
||||||
this.guideNode = this.canvas.node.getChildByName('Guide');
|
this.guideNode = this.canvas.node.getChildByName('Guide');
|
||||||
@@ -65,11 +71,15 @@ export class PlayerController extends Component {
|
|||||||
|
|
||||||
this.initProps();
|
this.initProps();
|
||||||
// this.showBonusPopup()
|
// this.showBonusPopup()
|
||||||
|
// this.scheduleOnce(() => {
|
||||||
|
// this.showBonusPopup()
|
||||||
|
// }, 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
onDestroy() {
|
onDestroy() {
|
||||||
// 移除触摸事件
|
// 移除触摸事件
|
||||||
input.off(Input.EventType.TOUCH_START, this.onTouchStart, this);
|
input.off(Input.EventType.TOUCH_START, this.onTouchStart, this);
|
||||||
|
this.clearPopupHideSchedule();
|
||||||
}
|
}
|
||||||
|
|
||||||
start() {
|
start() {
|
||||||
@@ -134,6 +144,11 @@ export class PlayerController extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private onTouchStart(event: EventTouch) {
|
private onTouchStart(event: EventTouch) {
|
||||||
|
if (this.activePopup) {
|
||||||
|
this.hideActivePopup();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!this.player || !this.camera || !this.pathfinder || this.isAttacking || this.isGameOver || this.isWin) return;
|
if (!this.player || !this.camera || !this.pathfinder || this.isAttacking || this.isGameOver || this.isWin) return;
|
||||||
|
|
||||||
this.guideNode.active = false;
|
this.guideNode.active = false;
|
||||||
@@ -626,6 +641,7 @@ export class PlayerController extends Component {
|
|||||||
// 所有动画完成后,播放升级动画并设置升级状态
|
// 所有动画完成后,播放升级动画并设置升级状态
|
||||||
this.playLevelUpAnimation();
|
this.playLevelUpAnimation();
|
||||||
this.isUpgraded = true;
|
this.isUpgraded = true;
|
||||||
|
this.showWeaponBonusPopup();
|
||||||
console.log('所有道具飞行动画完成,玩家已升级,后续动画将使用升级版本');
|
console.log('所有道具飞行动画完成,玩家已升级,后续动画将使用升级版本');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -663,64 +679,60 @@ export class PlayerController extends Component {
|
|||||||
* 根据当前镜头位置和正交高度,将奖励节点正确缩放并移动到画面正中间
|
* 根据当前镜头位置和正交高度,将奖励节点正确缩放并移动到画面正中间
|
||||||
*/
|
*/
|
||||||
public showBonusPopup() {
|
public showBonusPopup() {
|
||||||
if (!this.bonus || !this.camera || !this.canvas) {
|
this.showPopupAtCameraCenter(this.bonus, '奖励弹窗');
|
||||||
console.warn('奖励节点、相机或画布未设置,无法显示奖励弹窗');
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 弹出武器奖励
|
||||||
|
*/
|
||||||
|
public showWeaponBonusPopup() {
|
||||||
|
this.showPopupAtCameraCenter(this.bonusWuqi, '武器奖励');
|
||||||
|
}
|
||||||
|
|
||||||
|
private showPopupAtCameraCenter(popup: Node | null, nameForLog: string) {
|
||||||
|
if (!popup || !this.camera || !this.canvas) {
|
||||||
|
console.warn(`${nameForLog}节点、相机或画布未设置,无法显示${nameForLog}`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 确保奖励节点是激活状态
|
this.clearPopupHideSchedule();
|
||||||
this.bonus.active = true;
|
|
||||||
|
popup.active = true;
|
||||||
|
|
||||||
// 获取相机位置,相机所在的世界坐标就是当前屏幕的中心
|
|
||||||
const cameraPos = this.camera.node.position;
|
const cameraPos = this.camera.node.position;
|
||||||
const orthoHeight = this.camera.orthoHeight;
|
const orthoHeight = this.camera.orthoHeight;
|
||||||
|
|
||||||
// 直接将弹窗设置到相机位置(屏幕中心)
|
popup.setPosition(cameraPos.x, cameraPos.y, 0);
|
||||||
this.bonus.setPosition(cameraPos.x, cameraPos.y, 0);
|
|
||||||
|
|
||||||
// 计算合适的缩放比例,确保弹窗在不同正交高度下都能正确显示
|
const baseScale = 0.8;
|
||||||
// 基础缩放比例
|
|
||||||
const baseScale = 1.0;
|
|
||||||
|
|
||||||
// 根据正交高度调整缩放,确保弹窗大小合适
|
|
||||||
// 假设标准正交高度为500,以此为基准进行缩放
|
|
||||||
const standardOrthoHeight = 500;
|
const standardOrthoHeight = 500;
|
||||||
const scaleRatio = standardOrthoHeight / orthoHeight;
|
const scaleRatio = standardOrthoHeight / orthoHeight;
|
||||||
const finalScale = baseScale * scaleRatio;
|
const finalScale = baseScale * scaleRatio;
|
||||||
|
|
||||||
// 设置奖励节点的缩放
|
popup.setScale(finalScale, finalScale, 1);
|
||||||
this.bonus.setScale(finalScale, finalScale, 1);
|
|
||||||
|
|
||||||
// 添加弹窗出现动画
|
this.activePopup = popup;
|
||||||
this.playBonusPopupAnimation();
|
this.activePopupName = nameForLog;
|
||||||
|
|
||||||
// 监听领取按钮
|
this.playPopupAppearAnimation(popup, nameForLog);
|
||||||
const receiveButton = this.bonus.getChildByName('Receive');
|
|
||||||
const bonusWuqi = this.bonus.getChildByName('BonusWuqi');
|
this.pendingPopupHide = () => {
|
||||||
const bonusAnim = this.bonus.getChildByName('BonusAnim');
|
this.pendingPopupHide = null;
|
||||||
console.log('this.bonus', this.bonus);
|
this.hideActivePopup();
|
||||||
if (receiveButton) {
|
};
|
||||||
receiveButton.on('click', () => {
|
|
||||||
bonusAnim.active = false
|
this.scheduleOnce(this.pendingPopupHide, 3);
|
||||||
bonusWuqi.active = true
|
|
||||||
}, this);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 播放奖励弹窗出现动画
|
* 播放奖励弹窗出现动画
|
||||||
*/
|
*/
|
||||||
private playBonusPopupAnimation() {
|
private playPopupAppearAnimation(popup: Node, nameForLog: string) {
|
||||||
if (!this.bonus) return;
|
const originalScale = popup.scale.clone();
|
||||||
|
|
||||||
// 保存原始缩放
|
popup.setScale(0.1, 0.1, 1);
|
||||||
const originalScale = this.bonus.scale.clone();
|
|
||||||
|
|
||||||
// 初始状态设置为很小
|
tween(popup)
|
||||||
this.bonus.setScale(0.1, 0.1, 1);
|
|
||||||
|
|
||||||
// 创建弹窗弹出动画
|
|
||||||
tween(this.bonus)
|
|
||||||
.to(0.3, {
|
.to(0.3, {
|
||||||
scale: new Vec3(originalScale.x * 1.2, originalScale.y * 1.2, originalScale.z)
|
scale: new Vec3(originalScale.x * 1.2, originalScale.y * 1.2, originalScale.z)
|
||||||
}, {
|
}, {
|
||||||
@@ -732,7 +744,7 @@ export class PlayerController extends Component {
|
|||||||
easing: 'sineInOut'
|
easing: 'sineInOut'
|
||||||
})
|
})
|
||||||
.call(() => {
|
.call(() => {
|
||||||
console.log('奖励弹窗显示完成');
|
console.log(`${nameForLog}显示完成`);
|
||||||
})
|
})
|
||||||
.start();
|
.start();
|
||||||
}
|
}
|
||||||
@@ -743,17 +755,52 @@ export class PlayerController extends Component {
|
|||||||
public hideBonusPopup() {
|
public hideBonusPopup() {
|
||||||
if (!this.bonus) return;
|
if (!this.bonus) return;
|
||||||
|
|
||||||
// 创建弹窗消失动画
|
if (this.activePopup === this.bonus) {
|
||||||
tween(this.bonus)
|
this.hideActivePopup();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.bonus.active) return;
|
||||||
|
|
||||||
|
this.hidePopupWithAnimation(this.bonus, '奖励弹窗');
|
||||||
|
}
|
||||||
|
|
||||||
|
private hideActivePopup() {
|
||||||
|
if (!this.activePopup) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const popupToHide = this.activePopup;
|
||||||
|
const nameForLog = this.activePopupName || '弹窗';
|
||||||
|
|
||||||
|
this.clearPopupHideSchedule();
|
||||||
|
|
||||||
|
this.activePopup = null;
|
||||||
|
this.activePopupName = null;
|
||||||
|
|
||||||
|
this.hidePopupWithAnimation(popupToHide, nameForLog);
|
||||||
|
}
|
||||||
|
|
||||||
|
private hidePopupWithAnimation(popup: Node, nameForLog: string) {
|
||||||
|
tween(popup).stop();
|
||||||
|
|
||||||
|
tween(popup)
|
||||||
.to(0.2, {
|
.to(0.2, {
|
||||||
scale: new Vec3(0.1, 0.1, 1)
|
scale: new Vec3(0.1, 0.1, 1)
|
||||||
}, {
|
}, {
|
||||||
easing: 'backIn'
|
easing: 'backIn'
|
||||||
})
|
})
|
||||||
.call(() => {
|
.call(() => {
|
||||||
this.bonus.active = false;
|
popup.active = false;
|
||||||
console.log('奖励弹窗已隐藏');
|
console.log(`${nameForLog}已隐藏`);
|
||||||
})
|
})
|
||||||
.start();
|
.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private clearPopupHideSchedule() {
|
||||||
|
if (this.pendingPopupHide) {
|
||||||
|
this.unschedule(this.pendingPopupHide);
|
||||||
|
this.pendingPopupHide = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -45,8 +45,16 @@ export class Shadow2D extends Component {
|
|||||||
update(dt: number) {
|
update(dt: number) {
|
||||||
if (!this.shadowNode || !this.target) return;
|
if (!this.shadowNode || !this.target) return;
|
||||||
|
|
||||||
|
if (!this.target.active) {
|
||||||
|
this.shadowNode.active = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// 始终保持在角色底部(比如角色动画高度变化时也能跟随)
|
// 始终保持在角色底部(比如角色动画高度变化时也能跟随)
|
||||||
let ui = this.target.getComponent(UITransform);
|
let ui = this.target.getComponent(UITransform);
|
||||||
|
|
||||||
|
if (!ui) return;
|
||||||
|
|
||||||
this.shadowNode.setPosition(0, -ui.height / 2);
|
this.shadowNode.setPosition(0, -ui.height / 2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user