I’ve applied some logic for duplicating prefabs in my recreation, nevertheless it’s not working very nicely!
Has anybody else tried making a Wrapping World in any respect? Is duplicating objects the right method to go? I’m actually in search of affirmation that duplicating objects is the easiest way to go… In that case, I’ll persevere for a bit, failing that I could need to simplify my recreation!
import { _decorator, Element, Node, Vec3, instantiate, Digital camera, view, js, RigidBody2D, UITransform, NodePool, Prefab } from 'cc';
import { GameConstants } from './constants';
const { ccclass, property } = _decorator;
import { GameObject } from './GameObject';
@ccclass('BoundaryDuplicator')
export class BoundaryDuplicator extends Element {
@property(Node)
participant: Node | null = null;
@property(Digital camera)
digital camera: Digital camera | null = null;
@property({ sort: [Prefab]})
prefabs: Prefab[] = [];
non-public clones: Map = new Map();
non-public prefabPools: Map = new Map();
onLoad() {
for(const prefab of this.prefabs) {
this.createPoolForPrefab(prefab);
}
}
lateUpdate(deltaTime: quantity) {
if (!this.participant || !this.digital camera || !this.node) {
console.warn('Participant, digital camera, or world node is lacking!');
return;
}
const visibleBounds = this.getVisibleBounds();
const kids = this.node.kids.filter(youngster => !youngster.identify.contains('_Clone'));
for (const youngster of youngsters) {
const prefab = this.getPrefabForNode(youngster);
if(prefab) {
this.updateClones(youngster, visibleBounds, prefab);
}
}
}
non-public getVisibleBounds(): { min: Vec3; max: Vec3 } {
if (!this.digital camera) {
throw new Error("Digital camera is just not set.");
}
const orthoHeight = this.digital camera.orthoHeight;
const aspectRatio = view.getVisibleSize().width / view.getVisibleSize().peak;
const halfWidth = orthoHeight * aspectRatio;
const halfHeight = orthoHeight;
const cameraPosition = this.digital camera.node.place;
return {
min: new Vec3(cameraPosition.x - halfWidth, cameraPosition.y - halfHeight, 0),
max: new Vec3(cameraPosition.x + halfWidth, cameraPosition.y + halfHeight, 0),
};
}
non-public updateClones(node: Node, visibleBounds: { min: Vec3; max: Vec3 }, prefab: Prefab) {
const basePosition = node.place.clone();
if(!this.clones.has(node)) {
this.clones.set(node, []);
}
const nodeClones = this.clones.get(node);
const objectSize = this.getObjectSize(node);
const offsets = [
{ x: -GameConstants.WORLD.WIDTH, y: 0 }, // Left
{ x: GameConstants.WORLD.WIDTH, y: 0 }, // Right
{ x: 0, y: -GameConstants.WORLD.HEIGHT }, // Bottom
{ x: 0, y: GameConstants.WORLD.HEIGHT }, // Top
{ x: -GameConstants.WORLD.WIDTH, y: -GameConstants.WORLD.HEIGHT }, // Bottom-Left
{ x: -GameConstants.WORLD.WIDTH, y: GameConstants.WORLD.HEIGHT }, // Top-Left
{ x: GameConstants.WORLD.WIDTH, y: -GameConstants.WORLD.HEIGHT }, // Bottom-Right
{ x: GameConstants.WORLD.WIDTH, y: GameConstants.WORLD.HEIGHT }, // Top-Right
];
offsets.forEach((offset, index) => {
const clonePosition = new Vec3(
basePosition.x + offset.x,
basePosition.y + offset.y,
basePosition.z
);
const inView =
clonePosition.x + objectSize.width / 2 >= visibleBounds.min.x &&
clonePosition.x - objectSize.width / 2 = visibleBounds.min.y &&
clonePosition.y - objectSize.peak / 2 0) {
clone = pool.get();
} else {
clone = instantiate(prefab);
}
this.copyOrRemoveProperties(authentic, clone);
const gameObjectComponent = clone.getComponent(GameObject);
if (gameObjectComponent) {
gameObjectComponent.originalObject = authentic;
}
return clone;
}
non-public copyOrRemoveProperties(authentic: Node, clone: Node) {
clone.setRotation(authentic.getRotation());
clone.setScale(authentic.getScale());
const originalRigidBody = authentic.getComponent(RigidBody2D);
const cloneRigidBody = clone.getComponent(RigidBody2D);
if(originalRigidBody && cloneRigidBody) {
cloneRigidBody.linearVelocity = originalRigidBody.linearVelocity.clone();
cloneRigidBody.angularVelocity = originalRigidBody.angularVelocity;
}
}
non-public returnToPool(prefab: Prefab, node: Node) {
const pool = this.prefabPools.get(prefab);
if(pool) {
pool.put(node);
} else {
node.destroy();
}
}
non-public getPrefabForNode(node: Node): Prefab | null {
for (const prefab of this.prefabs) {
if(node.identify.startsWith(prefab.information.identify)) {
return prefab;
}
}
return null;
}
non-public getObjectSize(node: Node): { width: quantity; peak: quantity } {
const uiTransform = node.getComponent(UITransform);
if (uiTransform) {
return {
width: uiTransform.contentSize.width,
peak: uiTransform.contentSize.peak,
};
}
return { width: 0, peak: 0 };
}
}
import { _decorator, Element, Node } from 'cc';
const { ccclass, property } = _decorator;
@ccclass('GameObject')
export class GameObject extends Element {
originalObject: Node | null = null;
onDisable() {
if (this. originalObject) {
this.originalObject.removeFromParent();
this.originalObject.destroy();
this.originalObject = null;
}
}
onDestroy(): void {
if (this.originalObject) {
this.originalObject.removeFromParent();
this.originalObject.destroy();
this.originalObject = null;
}
}
}