Skip to content
ProjectileMovement

Gameplay / ProjectileMovement

ProjectileMovement Class ​

Projectile movement function class

ProjectileMovement It is a functional component used to deal with flying objects in the game, such as bullets, rockets, projectile, etc.

Imagine that you control a character in the game, and you want him to fire a bullet. At this time, you can use the ProjectileMovement component to process the bullet movement.

The function of this component is like attaching an engine to a bullet so that it can fly automatically. You only need to set the speed and direction of the bullet, and the component will automatically calculate the trajectory of the bullet according to these parameters, and move it to the correct position. In this way, you don't need to manually write complex movement logic, but instead leave it to ProjectileMovement to handle.

In addition to basic mobility features, ProjectileMovement also offers some other features. For example, you can set the maximum flight distance or lifecycle of a bullet, beyond which the bullet will be automatically destroyed. You can also set up collision detection for bullets, which can trigger corresponding effects or damage when bullets collide with other objects.

Please turn off the physical simulation for the bound logical object by yourself. During the motion, the camera, restricted area, and functional class will be ignored and mobile synchronization will not be considered.

Implements ​

Table of contents ​

Properties ​

onProjectileHit: MulticastDelegate<(hitGameObject: GameObject, hitResult: HitResult) => void>
Trigger binding function when throwing object hits object
onProjectileHomingFail: MulticastDelegate<() => void>
Projectile tracking failure triggers the binding function (tracking failure specifically refers to the disappearance of the target, if and only if triggered once)
onProjectileLifeEnd: MulticastDelegate<() => void>
Trigger binding function when throwing object ends motion cycle
owner: Character
The holder of the projectile, which is convenient for the user to specify the character object to launch.

Accessors ​

acceleration(): number
The acceleration (cm/s) of the movement of the projectile, a positive value will accelerate the projectile and a negative value will decelerate. Default: 0, range: [-100000010000].
gravityScale(): number
The multiplier of the impact of world gravity on a projectile, where a positive value causes the projectile to fall, a negative value increases, and 0 causes the projectile to move in a straight line. Default: 1, range: [-10, 10].
homingAcceleration(): number
Acceleration towards the target object (cm/s). Default: 10000. Range: [0, 10000].
homingTarget(): GameObject
The target object tracked by the projectile will accelerate to the target when the target object is not empty. default: null。
initialSpeed(): number
The initial movement speed of the projectile (cm/s), default: 5000, range: [110000], the setting will not take effect after launching
isRotationFollowsVelocity(): boolean
Does the forward direction of the projectile (and the mounted object) always follow the direction of motion. True: Follow. False: Do not follow. default: true。
lifeSpan(): number
The maximum duration of the projectile's existence (s), 0 means there is no limit. Default: 10. Range: [0, 1000].
maxSpeed(): number
The maximum movement speed of the projectile (cm/s), 0 means there is no limit. Default: 0, range: [0100000].
speedRetention(): number
The proportion of the projectile maintaining its original speed after collision. 0 means that the speed is cleared directly after collision. Default: 0.6. Range: [0,1].
status(): ProjectileMovementStatus
The current state of the projectile

Methods ​

destroy([destroy](mw.ProjectileMovement.md#destroy)WithObject?): void other
Destroy projectile, that is, destroy the moving component and collision component under the object. You can choose whether to destroy it together with the associated object.
getRelatedGameObject(): GameObject other
Get associated logical objects
getTrajectory(startDirection: Vector, density: number, duration: number): Vector[] other
Obtain the predicted motion trajectory
getVelocity(): Vector other
Get current speed
launch(direction: Vector): void other
launch
pause(): void other
Pause movement and switch from Launched state to Ready state
resume(): void other
Continue exercising and switch from Ready state to Launched state
setRelatedGameObject(value: GameObject): void other
Set up a new associated logical object
setVelocity(v: Vector): void other
Set current speed

Construct function classes through configuration objects

Parameters ​

relatedGameObject GameObjectThe new associated logical object will generate component for it
config? ProjectileMovementConfigBatch read configuration default: null

Properties ​

onProjectileHit ​

• onProjectileHit: MulticastDelegate<(hitGameObject: GameObject, hitResult: HitResult) => void>

Trigger binding function when throwing object hits object


onProjectileHomingFail ​

• onProjectileHomingFail: MulticastDelegate<() => void>

Projectile tracking failure triggers the binding function (tracking failure specifically refers to the disappearance of the target, if and only if triggered once)


onProjectileLifeEnd ​

• onProjectileLifeEnd: MulticastDelegate<() => void>

Trigger binding function when throwing object ends motion cycle


owner ​

• owner: Character

The holder of the projectile, which is convenient for the user to specify the character object to launch.

Accessors ​

acceleration ​

• get acceleration(): number

• set acceleration(value): void

The acceleration (cm/s) of the movement of the projectile, a positive value will accelerate the projectile and a negative value will decelerate. Default: 0, range: [-100000010000].

Returns ​

numberProjectileMovementConfig.acceleration

The acceleration (cm/s) of the movement of the projectile, a positive value will accelerate the projectile and a negative value will decelerate. Default: 0, range: [-100000010000].

Parameters ​

valuenumber

Implementation of ​

ProjectileMovementConfig.acceleration


gravityScale ​

• get gravityScale(): number

• set gravityScale(value): void

The multiplier of the impact of world gravity on a projectile, where a positive value causes the projectile to fall, a negative value increases, and 0 causes the projectile to move in a straight line. Default: 1, range: [-10, 10].

Returns ​

numberProjectileMovementConfig.gravityScale

The multiplier of the impact of world gravity on a projectile, where a positive value causes the projectile to fall, a negative value increases, and 0 causes the projectile to move in a straight line. Default: 1, range: [-10, 10].

Parameters ​

valuenumber

Implementation of ​

ProjectileMovementConfig.gravityScale


homingAcceleration ​

• get homingAcceleration(): number

• set homingAcceleration(value): void

Acceleration towards the target object (cm/s). Default: 10000. Range: [0, 10000].

Returns ​

numberProjectileMovementConfig.homingAcceleration

Acceleration towards the target object (cm/s). Default: 10000. Range: [0, 10000].

Parameters ​

valuenumber

Implementation of ​

ProjectileMovementConfig.homingAcceleration


homingTarget ​

• get homingTarget(): GameObject

• set homingTarget(value): void

The target object tracked by the projectile will accelerate to the target when the target object is not empty. default: null。

Returns ​

GameObjectProjectileMovementConfig.homingTarget

The target object tracked by the projectile will accelerate to the target when the target object is not empty. default: null。

Parameters ​

valueGameObject

Implementation of ​

ProjectileMovementConfig.homingTarget


initialSpeed ​

• get initialSpeed(): number

• set initialSpeed(value): void

The initial movement speed of the projectile (cm/s), default: 5000, range: [110000], the setting will not take effect after launching

Returns ​

numberProjectileMovementConfig.initialSpeed

The initial movement speed of the projectile (cm/s), default: 5000, range: [110000], the setting will not take effect after launching

Parameters ​

valuenumber

Implementation of ​

ProjectileMovementConfig.initialSpeed


isRotationFollowsVelocity ​

• get isRotationFollowsVelocity(): boolean

• set isRotationFollowsVelocity(value): void

Does the forward direction of the projectile (and the mounted object) always follow the direction of motion. True: Follow. False: Do not follow. default: true。

Returns ​

booleanProjectileMovementConfig.isRotationFollowsVelocity

Does the forward direction of the projectile (and the mounted object) always follow the direction of motion. True: Follow. False: Do not follow. default: true。

Parameters ​

valueboolean

Implementation of ​

ProjectileMovementConfig.isRotationFollowsVelocity


lifeSpan ​

• get lifeSpan(): number

• set lifeSpan(value): void

The maximum duration of the projectile's existence (s), 0 means there is no limit. Default: 10. Range: [0, 1000].

Returns ​

numberProjectileMovementConfig.lifeSpan

The maximum duration of the projectile's existence (s), 0 means there is no limit. Default: 10. Range: [0, 1000].

Parameters ​

valuenumber

Implementation of ​

ProjectileMovementConfig.lifeSpan


maxSpeed ​

• get maxSpeed(): number

• set maxSpeed(value): void

The maximum movement speed of the projectile (cm/s), 0 means there is no limit. Default: 0, range: [0100000].

Returns ​

numberProjectileMovementConfig.maxSpeed

The maximum movement speed of the projectile (cm/s), 0 means there is no limit. Default: 0, range: [0100000].

Parameters ​

valuenumber

Implementation of ​

ProjectileMovementConfig.maxSpeed


speedRetention ​

• get speedRetention(): number

• set speedRetention(value): void

The proportion of the projectile maintaining its original speed after collision. 0 means that the speed is cleared directly after collision. Default: 0.6. Range: [0,1].

Returns ​

numberProjectileMovementConfig.speedRetention

The proportion of the projectile maintaining its original speed after collision. 0 means that the speed is cleared directly after collision. Default: 0.6. Range: [0,1].

Parameters ​

valuenumber

Implementation of ​

ProjectileMovementConfig.speedRetention


status ​

• get status(): ProjectileMovementStatus

The current state of the projectile

Returns ​

ProjectileMovementStatus

Methods ​

destroy ​

• destroy(destroyWithObject?): void other

Destroy projectile, that is, destroy the moving component and collision component under the object. You can choose whether to destroy it together with the associated object.

Parameters ​

destroyWithObject? booleanWhether to delete default: true together with the object

Usage example: create a script and place it in the object bar. copy the following "Example_ProjectileMovement_Destroy" code in the script and save it. Run the game. Five balls will be generated in the scene for launching. Bind the function to the delegate of the event corresponding to the emitter. Press key "1" to launch the sphere object associated with the projectile. press key "2" to switch the sphere object associated with the projectile and delete the previous one. Note that you need to wait until the sphere stops before switching, otherwise the sphere object associated with the projectile will be switched in advance; the object code is set as follows:

ts
@Component
export default class Example_ProjectileMovement_Destroy extends Script {

   protected async onStart(): Promise<void> {

       // The following logic is executed on the server side
       if(SystemUtil.isServer()) {

           // Create a model array balls and identify curBall.
           let balls = new Array<Model>();
           let curBall = 0;

           // Generate 5 balls asynchronously ahead and place them in the array of balls.
           for (let i = 0;
i < 5;
i++) {
               let ball = await GameObject.asyncSpawn("84121") as Model;
               ball.worldTransform.position = new Vector(200, i * 100, 25);
               ball.name = "ball" + i;
               ball.setCollision(CollisionStatus.QueryCollisionOnly);
               balls.push(ball);
           }

           // Create a projectile.
           let projectile = new ProjectileMovement(balls[curBall]);

           // Set the initial launch speed to 1000.
           projectile.initialSpeed = 1000;

           // Bind a function to the hit delegate. When the hit object is a target, play a hit effect. After 0.5s, delete the target.
           projectile.onProjectileHit.add((hitGameObject, HitResult) => {
               EffectService.playAtPosition("99599", HitResult.impactPoint, {scale: new Vector(5, 5, 5)});
           });

           // Add the "LAUNCH" event listener sent by the client and emit the ball to the front right.
           Event.addClientListener("LAUNCH", async (player: Player) => {
               projectile.launch(new Vector(1, 1, 1));
           });

           // Add the "DESTROY" event listener sent by the client, delete the sphere object from the array, and switch the objects associated with the projectile.
           Event.addClientListener("DESTROY", async (player: Player) => {
               console.error("DESTROY");
               let deleteBall = projectile.getRelatedGameObject() as Model;
               let deleteIndex = balls.indexOf(deleteBall);
               balls.splice(deleteIndex, 1);
               if(balls.length > 0) {
                   curBall = (deleteIndex) % balls.length;
                   projectile.setRelatedGameObject(balls[curBall]);
                   deleteBall.destroy();
               } else {
                   projectile.destroy(true);
               }
           });
       }

       // The following logic is executed on the client side
       if(SystemUtil.isClient()) {
           // Add a button method: Press button "1" to send a "LAUNCH" event to the server and launch a ball.
           InputUtil.onKeyDown(Keys.One, () => {
               Event.dispatchToServer("LAUNCH");
           });

           // Add a key method: press key "2", send a "DESTROY" event to the server, switch to the next sphere and delete the previous one.
           InputUtil.onKeyDown(Keys.Two, () => {
               Event.dispatchToServer("DESTROY");
           });
       }
   }
}
@Component
export default class Example_ProjectileMovement_Destroy extends Script {

   protected async onStart(): Promise<void> {

       // The following logic is executed on the server side
       if(SystemUtil.isServer()) {

           // Create a model array balls and identify curBall.
           let balls = new Array<Model>();
           let curBall = 0;

           // Generate 5 balls asynchronously ahead and place them in the array of balls.
           for (let i = 0;
i < 5;
i++) {
               let ball = await GameObject.asyncSpawn("84121") as Model;
               ball.worldTransform.position = new Vector(200, i * 100, 25);
               ball.name = "ball" + i;
               ball.setCollision(CollisionStatus.QueryCollisionOnly);
               balls.push(ball);
           }

           // Create a projectile.
           let projectile = new ProjectileMovement(balls[curBall]);

           // Set the initial launch speed to 1000.
           projectile.initialSpeed = 1000;

           // Bind a function to the hit delegate. When the hit object is a target, play a hit effect. After 0.5s, delete the target.
           projectile.onProjectileHit.add((hitGameObject, HitResult) => {
               EffectService.playAtPosition("99599", HitResult.impactPoint, {scale: new Vector(5, 5, 5)});
           });

           // Add the "LAUNCH" event listener sent by the client and emit the ball to the front right.
           Event.addClientListener("LAUNCH", async (player: Player) => {
               projectile.launch(new Vector(1, 1, 1));
           });

           // Add the "DESTROY" event listener sent by the client, delete the sphere object from the array, and switch the objects associated with the projectile.
           Event.addClientListener("DESTROY", async (player: Player) => {
               console.error("DESTROY");
               let deleteBall = projectile.getRelatedGameObject() as Model;
               let deleteIndex = balls.indexOf(deleteBall);
               balls.splice(deleteIndex, 1);
               if(balls.length > 0) {
                   curBall = (deleteIndex) % balls.length;
                   projectile.setRelatedGameObject(balls[curBall]);
                   deleteBall.destroy();
               } else {
                   projectile.destroy(true);
               }
           });
       }

       // The following logic is executed on the client side
       if(SystemUtil.isClient()) {
           // Add a button method: Press button "1" to send a "LAUNCH" event to the server and launch a ball.
           InputUtil.onKeyDown(Keys.One, () => {
               Event.dispatchToServer("LAUNCH");
           });

           // Add a key method: press key "2", send a "DESTROY" event to the server, switch to the next sphere and delete the previous one.
           InputUtil.onKeyDown(Keys.Two, () => {
               Event.dispatchToServer("DESTROY");
           });
       }
   }
}

getRelatedGameObject ​

• getRelatedGameObject(): GameObject other

Get associated logical objects

Returns ​

GameObjectRelated logical objects

Usage example: create a script and place it in the object bar. copy the following "Example_ProjectileMovement" code in the script and save it. Run the game. Five balls will be generated in the scene for launching. Bind the function to the delegate of the event corresponding to the emitter. Press button "1" to launch the ball object associated with the projectile. Press button "2" to switch the ball object associated with the projectile and delete the previous one. Note that you need to wait for the ball to stop before switching, otherwise the ball object associated with the projectile will be switched in advance; set the object code as follows:

ts
@Component
export default class Example_ProjectileMovement extends Script {

   protected async onStart(): Promise<void> {

       // The following logic is executed on the server side
       if(SystemUtil.isServer()) {

           // Create a model array balls and identify curBall.
           let balls = new Array<Model>();
           let curBall = 0;

           // Generate 5 balls asynchronously ahead and place them in the array of balls.
           for (let i = 0;
i < 5;
i++) {
               let ball = await GameObject.asyncSpawn("84121") as Model;
               ball.worldTransform.position = new Vector(200, i * 100, 25);
               ball.name = "ball" + i;
               ball.setCollision(CollisionStatus.QueryCollisionOnly);
               balls.push(ball);
           }

           // Create a projectile.
           let projectile = new ProjectileMovement(balls[curBall]);

           // Set the initial launch speed to 1000.
           projectile.initialSpeed = 1000;

           // Bind a function to the hit delegate. When the hit object is a target, play a hit effect. After 0.5s, delete the target.
           projectile.onProjectileHit.add((hitGameObject, HitResult) => {
               EffectService.playAtPosition("99599", HitResult.impactPoint, {scale: new Vector(5, 5, 5)});
           });

           // Add the "LAUNCH" event listener sent by the client and emit the ball to the front right.
           Event.addClientListener("LAUNCH", async (player: Player) => {
               projectile.launch(new Vector(1, 1, 1));
           });

           // Add the "DESTROY" event listener sent by the client, delete the sphere object from the array, and switch the objects associated with the projectile.
           Event.addClientListener("DESTROY", async (player: Player) => {
               console.error("DESTROY");
               let deleteBall = projectile.getRelatedGameObject() as Model;
               let deleteIndex = balls.indexOf(deleteBall);
               balls.splice(deleteIndex, 1);
               if(balls.length > 0) {
                   curBall = (deleteIndex) % balls.length;
                   projectile.setRelatedGameObject(balls[curBall]);
                   deleteBall.destroy();
               } else {
                   projectile.destroy(true);
               }
           });
       }

       // The following logic is executed on the client side
       if(SystemUtil.isClient()) {
           // Add a button method: Press button "1" to send a "LAUNCH" event to the server and launch a ball.
           InputUtil.onKeyDown(Keys.One, () => {
               Event.dispatchToServer("LAUNCH");
           });

           // Add a key method: press key "2", send a "DESTROY" event to the server, switch to the next sphere and delete the previous one.
           InputUtil.onKeyDown(Keys.Two, () => {
               Event.dispatchToServer("DESTROY");
           });
       }
   }
}
@Component
export default class Example_ProjectileMovement extends Script {

   protected async onStart(): Promise<void> {

       // The following logic is executed on the server side
       if(SystemUtil.isServer()) {

           // Create a model array balls and identify curBall.
           let balls = new Array<Model>();
           let curBall = 0;

           // Generate 5 balls asynchronously ahead and place them in the array of balls.
           for (let i = 0;
i < 5;
i++) {
               let ball = await GameObject.asyncSpawn("84121") as Model;
               ball.worldTransform.position = new Vector(200, i * 100, 25);
               ball.name = "ball" + i;
               ball.setCollision(CollisionStatus.QueryCollisionOnly);
               balls.push(ball);
           }

           // Create a projectile.
           let projectile = new ProjectileMovement(balls[curBall]);

           // Set the initial launch speed to 1000.
           projectile.initialSpeed = 1000;

           // Bind a function to the hit delegate. When the hit object is a target, play a hit effect. After 0.5s, delete the target.
           projectile.onProjectileHit.add((hitGameObject, HitResult) => {
               EffectService.playAtPosition("99599", HitResult.impactPoint, {scale: new Vector(5, 5, 5)});
           });

           // Add the "LAUNCH" event listener sent by the client and emit the ball to the front right.
           Event.addClientListener("LAUNCH", async (player: Player) => {
               projectile.launch(new Vector(1, 1, 1));
           });

           // Add the "DESTROY" event listener sent by the client, delete the sphere object from the array, and switch the objects associated with the projectile.
           Event.addClientListener("DESTROY", async (player: Player) => {
               console.error("DESTROY");
               let deleteBall = projectile.getRelatedGameObject() as Model;
               let deleteIndex = balls.indexOf(deleteBall);
               balls.splice(deleteIndex, 1);
               if(balls.length > 0) {
                   curBall = (deleteIndex) % balls.length;
                   projectile.setRelatedGameObject(balls[curBall]);
                   deleteBall.destroy();
               } else {
                   projectile.destroy(true);
               }
           });
       }

       // The following logic is executed on the client side
       if(SystemUtil.isClient()) {
           // Add a button method: Press button "1" to send a "LAUNCH" event to the server and launch a ball.
           InputUtil.onKeyDown(Keys.One, () => {
               Event.dispatchToServer("LAUNCH");
           });

           // Add a key method: press key "2", send a "DESTROY" event to the server, switch to the next sphere and delete the previous one.
           InputUtil.onKeyDown(Keys.Two, () => {
               Event.dispatchToServer("DESTROY");
           });
       }
   }
}

getTrajectory ​

• getTrajectory(startDirection, density, duration): Vector[] other

Obtain the predicted motion trajectory

Parameters ​

startDirection VectorLaunch direction
density numberThe density of prediction points is equal to the simulated frame rate range: no limit, the larger the value, the finer the track, and the greater the performance consumption type: floating point
duration numberThe predicted duration is equivalent to the simulated duration range: no limit, the larger the value, the longer the track, the greater the performance consumption type: floating point

Returns ​

Vector[]Trajectory point coordinate array

Precautions

Launched Not effective when calling status


getVelocity ​

• getVelocity(): Vector other

Get current speed

Returns ​

VectorCurrent speed

Usage example: create a script and place it in the object bar. copy the following "Example_ProjectileMovement" code in the script and save it to run the game. Press key "1" to launch a rocket. The setting object code is as follows:

ts
@Component
export default class Example_ProjectileMovement extends Script {

   protected async onStart(): Promise<void> {

       // The following logic is executed on the server side
       if(SystemUtil.isServer()) {

           // Generate a rocket model in r (2000, 0, 0).
           let rocket = await GameObject.asyncSpawn("162807") as Model;
           rocket.worldTransform.position = new Vector(2000, 0, 0);

           // Change the collision status of the rocket to no collision
           rocket.setCollision(CollisionStatus.Off);

           // Create a projectile.
           let projectile = new ProjectileMovement(rocket);

           // Set the initial launch speed to 1.
           projectile.initialSpeed = 1;
           // Set the maximum speed to 1000.
           projectile.maxSpeed = 1000;
           // Set the launch acceleration to 200
           projectile.acceleration = 200;
           // Set gravity scaling to 0.
           projectile.gravityScale = 0;
           // Set the rotation of the projectile not to follow the speed direction.
           projectile.isRotationFollowsVelocity = false;
           // Set the movement time of projectile to 10 seconds.
           projectile.lifeSpan = 10;

           // Add a 'LAUNCH' event listener sent by the client and launch the rocket upwards.
           Event.addClientListener("LAUNCH", async (player: Player) => {
               projectile.launch(new Vector(0, 0, 1));
               // Broadcast client to mount rocket tail flame special effects
               Event.dispatchToAllClient("TAIL", rocket.gameObjectId);
               // Every 0.1 seconds, the current speed of the rocket will be broadcasted to the client
               let scaleInterval = TimeUtil.setInterval(() => {
                   if(projectile.getVelocity().length > 999) {
                       projectile.setVelocity(Vector.zero);
                       TimeUtil.clearInterval(scaleInterval);
                       rocket.worldTransform.position = new Vector(2000, 0, 0);
                   }
                   Event.dispatchToAllClient("SCALING", rocket.gameObjectId, projectile.getVelocity());
               }, 0.1);
           });
       }

       // The following logic is executed on the client side
       if(SystemUtil.isClient()) {
           // Add a key method: press key "1" to send a "LAUNCH" event to the server and launch the rocket
           InputUtil.onKeyDown(Keys.One, () => {
               Event.dispatchToServer("LAUNCH");
           });

           // Add a "TAIL" event listener sent by the server to mount the rocket's tail flame.
           Event.addServerListener("TAIL", async (rocketId: string) => {
               let rocket = await GameObject.asyncFindGameObjectById(rocketId);
               if(typeof(rocket.getChildByName("tail")) != "undefined") {
                   return;
               }
               let tail = await GameObject.asyncSpawn("144098") as Effect;
               tail.name = "tail";
               tail.parent = rocket;
               tail.localTransform.position = Vector.zero;
           });

           // Add the "SCALING" event listener sent by the server, and scale the tail flame according to the speed
           Event.addServerListener("SCALING", async (rocketId: string, velocity: Vector) => {
               let rocket = await GameObject.asyncFindGameObjectById(rocketId);
               let tail = rocket.getChildByName("tail");
               if(tail) {
                   tail.worldTransform.scale = Vector.one.multiply(velocity.length / 250);
               }
           });
       }
   }
}
@Component
export default class Example_ProjectileMovement extends Script {

   protected async onStart(): Promise<void> {

       // The following logic is executed on the server side
       if(SystemUtil.isServer()) {

           // Generate a rocket model in r (2000, 0, 0).
           let rocket = await GameObject.asyncSpawn("162807") as Model;
           rocket.worldTransform.position = new Vector(2000, 0, 0);

           // Change the collision status of the rocket to no collision
           rocket.setCollision(CollisionStatus.Off);

           // Create a projectile.
           let projectile = new ProjectileMovement(rocket);

           // Set the initial launch speed to 1.
           projectile.initialSpeed = 1;
           // Set the maximum speed to 1000.
           projectile.maxSpeed = 1000;
           // Set the launch acceleration to 200
           projectile.acceleration = 200;
           // Set gravity scaling to 0.
           projectile.gravityScale = 0;
           // Set the rotation of the projectile not to follow the speed direction.
           projectile.isRotationFollowsVelocity = false;
           // Set the movement time of projectile to 10 seconds.
           projectile.lifeSpan = 10;

           // Add a 'LAUNCH' event listener sent by the client and launch the rocket upwards.
           Event.addClientListener("LAUNCH", async (player: Player) => {
               projectile.launch(new Vector(0, 0, 1));
               // Broadcast client to mount rocket tail flame special effects
               Event.dispatchToAllClient("TAIL", rocket.gameObjectId);
               // Every 0.1 seconds, the current speed of the rocket will be broadcasted to the client
               let scaleInterval = TimeUtil.setInterval(() => {
                   if(projectile.getVelocity().length > 999) {
                       projectile.setVelocity(Vector.zero);
                       TimeUtil.clearInterval(scaleInterval);
                       rocket.worldTransform.position = new Vector(2000, 0, 0);
                   }
                   Event.dispatchToAllClient("SCALING", rocket.gameObjectId, projectile.getVelocity());
               }, 0.1);
           });
       }

       // The following logic is executed on the client side
       if(SystemUtil.isClient()) {
           // Add a key method: press key "1" to send a "LAUNCH" event to the server and launch the rocket
           InputUtil.onKeyDown(Keys.One, () => {
               Event.dispatchToServer("LAUNCH");
           });

           // Add a "TAIL" event listener sent by the server to mount the rocket's tail flame.
           Event.addServerListener("TAIL", async (rocketId: string) => {
               let rocket = await GameObject.asyncFindGameObjectById(rocketId);
               if(typeof(rocket.getChildByName("tail")) != "undefined") {
                   return;
               }
               let tail = await GameObject.asyncSpawn("144098") as Effect;
               tail.name = "tail";
               tail.parent = rocket;
               tail.localTransform.position = Vector.zero;
           });

           // Add the "SCALING" event listener sent by the server, and scale the tail flame according to the speed
           Event.addServerListener("SCALING", async (rocketId: string, velocity: Vector) => {
               let rocket = await GameObject.asyncFindGameObjectById(rocketId);
               let tail = rocket.getChildByName("tail");
               if(tail) {
                   tail.worldTransform.scale = Vector.one.multiply(velocity.length / 250);
               }
           });
       }
   }
}

launch ​

• launch(direction): void other

launch

Parameters ​

direction VectorEmission direction, if it is (0,0,0), it will be reset to the default value default: (1,0,0)

Precautions

Can be called in Ready state

Example usage: Create a script and place it in the object bar. Copy and save the following code "Instance-PProjectileMovement_Launch" in the script. Run the game, and a ball for firing and a wall for collision will be generated in the scene. Bind the function to the delegate of the event corresponding to the emitter. Press button "1" to launch the ball; press button "2" to temporarily stop the ball's movement; press button "3" to resume the ball's movement; set the object code as follows:

ts
@Component
export default class Example_ProjectileMovement_Launch extends Script {

   protected async onStart(): Promise<void> {

       // The following logic is executed on the server side
       if(SystemUtil.isServer()) {

           // Asynchronously generate a sphere at world coordinates (200, 0, 25)
           let ball = await GameObject.asyncSpawn("84121") as Model;
           ball.worldTransform.position = new Vector(200, 0, 25);
           ball.name = "ball";
           ball.setCollision(CollisionStatus.QueryCollisionOnly);

           // Asynchronously generate a wall at world coordinates (1000, 0, 0)
           let wall = await GameObject.asyncSpawn("197386") as Model;
           wall.worldTransform.position = new Vector(1000, 0, 0);
           wall.worldTransform.scale = new Vector(1, 5, 5);
           wall.name = "wall";

           // Create a projectile.
           let projectile = new ProjectileMovement(ball);

           // Set the initial launch speed to 1500.
           projectile.initialSpeed = 1500;
           // Set gravity scaling to 1.
           projectile.gravityScale = 1;
           // Set the direction of the rotation of the projectile to follow the speed.
           projectile.isRotationFollowsVelocity = true;
           // Set the ratio of collision maintenance speed of projectile to 0.4.
           projectile.speedRetention = 0.4;

           // Bind a function to the hit delegate, print the hit information: character X launches object Y hits object Z, and play a hit effect.
           projectile.onProjectileHit.add((hitGameObject, HitResult) => {
               console.log( "Projectile " + projectile.getRelatedGameObject().name + " thrown by Character " + projectile.owner.displayName + " hits the " + hitGameObject.name);
               EffectService.playAtPosition("99599", HitResult.impactPoint);
           });

           // Bind a function to the end of life delegate of the projectile, and play a destroy effect.
           projectile.onProjectileLifeEnd.add(() => {
               EffectService.playAtPosition("133276", ball.worldTransform.position);
           });

           // Add a 'LAUNCH' event listener sent by the client and shoot the ball upwards.
           Event.addClientListener("LAUNCH", async (player: Player) => {
               // Set the owner as a Player character.
               projectile.owner = player.character;
               projectile.launch(new Vector(1, 0, 1));
           });

           // Add the "PAUSE" event listener sent by the client, which will pause the movement of the projectile and print the status.
           Event.addClientListener("PAUSE", async (player: Player) => {
               projectile.pause();
               console.log("Projectile status " + projectile.status);
           });

           // Add a "RESUME" event listener sent by the client to restore the motion of the projectile and print its status.
           Event.addClientListener("RESUME", async (player: Player) => {
               projectile.resume();
               console.log("Projectile status " + projectile.status);
           });
       }

       // The following logic is executed on the client side
       if(SystemUtil.isClient()) {
           // Add a key method: press key "1" to send a "LAUNCH" event to the server and launch the ball
           InputUtil.onKeyDown(Keys.One, () => {
               Event.dispatchToServer("LAUNCH");
           });

           // Add a key method: press key "2" to send a "PAUSE" event to the server and launch the ball
           InputUtil.onKeyDown(Keys.Two, () => {
               Event.dispatchToServer("PAUSE");
           });

           // Add a key method: press key "3" to send a "RESUME" event to the server and launch the ball
           InputUtil.onKeyDown(Keys.Three, () => {
               Event.dispatchToServer("RESUME");
           });
       }
   }
}
@Component
export default class Example_ProjectileMovement_Launch extends Script {

   protected async onStart(): Promise<void> {

       // The following logic is executed on the server side
       if(SystemUtil.isServer()) {

           // Asynchronously generate a sphere at world coordinates (200, 0, 25)
           let ball = await GameObject.asyncSpawn("84121") as Model;
           ball.worldTransform.position = new Vector(200, 0, 25);
           ball.name = "ball";
           ball.setCollision(CollisionStatus.QueryCollisionOnly);

           // Asynchronously generate a wall at world coordinates (1000, 0, 0)
           let wall = await GameObject.asyncSpawn("197386") as Model;
           wall.worldTransform.position = new Vector(1000, 0, 0);
           wall.worldTransform.scale = new Vector(1, 5, 5);
           wall.name = "wall";

           // Create a projectile.
           let projectile = new ProjectileMovement(ball);

           // Set the initial launch speed to 1500.
           projectile.initialSpeed = 1500;
           // Set gravity scaling to 1.
           projectile.gravityScale = 1;
           // Set the direction of the rotation of the projectile to follow the speed.
           projectile.isRotationFollowsVelocity = true;
           // Set the ratio of collision maintenance speed of projectile to 0.4.
           projectile.speedRetention = 0.4;

           // Bind a function to the hit delegate, print the hit information: character X launches object Y hits object Z, and play a hit effect.
           projectile.onProjectileHit.add((hitGameObject, HitResult) => {
               console.log( "Projectile " + projectile.getRelatedGameObject().name + " thrown by Character " + projectile.owner.displayName + " hits the " + hitGameObject.name);
               EffectService.playAtPosition("99599", HitResult.impactPoint);
           });

           // Bind a function to the end of life delegate of the projectile, and play a destroy effect.
           projectile.onProjectileLifeEnd.add(() => {
               EffectService.playAtPosition("133276", ball.worldTransform.position);
           });

           // Add a 'LAUNCH' event listener sent by the client and shoot the ball upwards.
           Event.addClientListener("LAUNCH", async (player: Player) => {
               // Set the owner as a Player character.
               projectile.owner = player.character;
               projectile.launch(new Vector(1, 0, 1));
           });

           // Add the "PAUSE" event listener sent by the client, which will pause the movement of the projectile and print the status.
           Event.addClientListener("PAUSE", async (player: Player) => {
               projectile.pause();
               console.log("Projectile status " + projectile.status);
           });

           // Add a "RESUME" event listener sent by the client to restore the motion of the projectile and print its status.
           Event.addClientListener("RESUME", async (player: Player) => {
               projectile.resume();
               console.log("Projectile status " + projectile.status);
           });
       }

       // The following logic is executed on the client side
       if(SystemUtil.isClient()) {
           // Add a key method: press key "1" to send a "LAUNCH" event to the server and launch the ball
           InputUtil.onKeyDown(Keys.One, () => {
               Event.dispatchToServer("LAUNCH");
           });

           // Add a key method: press key "2" to send a "PAUSE" event to the server and launch the ball
           InputUtil.onKeyDown(Keys.Two, () => {
               Event.dispatchToServer("PAUSE");
           });

           // Add a key method: press key "3" to send a "RESUME" event to the server and launch the ball
           InputUtil.onKeyDown(Keys.Three, () => {
               Event.dispatchToServer("RESUME");
           });
       }
   }
}

pause ​

• pause(): void other

Pause movement and switch from Launched state to Ready state

Precautions

Not effective when call in non launched state

Example usage: Create a script and place it in the object bar. Copy and save the following code "Instance-PProjectileMovement_Launch" in the script. Run the game, and a ball for firing and a wall for collision will be generated in the scene. Bind the function to the delegate of the event corresponding to the emitter. Press button "1" to launch the ball; press button "2" to temporarily stop the ball's movement; press button "3" to resume the ball's movement; set the object code as follows:

ts
@Component
export default class Example_ProjectileMovement_Launch extends Script {

   protected async onStart(): Promise<void> {

       // The following logic is executed on the server side
       if(SystemUtil.isServer()) {

           // Asynchronously generate a sphere at world coordinates (200, 0, 25)
           let ball = await GameObject.asyncSpawn("84121") as Model;
           ball.worldTransform.position = new Vector(200, 0, 25);
           ball.name = "ball";
           ball.setCollision(CollisionStatus.QueryCollisionOnly);

           // Asynchronously generate a wall at world coordinates (1000, 0, 0)
           let wall = await GameObject.asyncSpawn("197386") as Model;
           wall.worldTransform.position = new Vector(1000, 0, 0);
           wall.worldTransform.scale = new Vector(1, 5, 5);
           wall.name = "wall";

           // Create a projectile.
           let projectile = new ProjectileMovement(ball);

           // Set the initial launch speed to 1500.
           projectile.initialSpeed = 1500;
           // Set gravity scaling to 1.
           projectile.gravityScale = 1;
           // Set the direction of the rotation of the projectile to follow the speed.
           projectile.isRotationFollowsVelocity = true;
           // Set the ratio of collision maintenance speed of projectile to 0.4.
           projectile.speedRetention = 0.4;

           // Bind a function to the hit delegate, print the hit information: character X launches object Y hits object Z, and play a hit effect.
           projectile.onProjectileHit.add((hitGameObject, HitResult) => {
               console.log( "Projectile " + projectile.getRelatedGameObject().name + " thrown by Character " + projectile.owner.displayName + " hits the " + hitGameObject.name);
               EffectService.playAtPosition("99599", HitResult.impactPoint);
           });

           // Bind a function to the end of life delegate of the projectile, and play a destroy effect.
           projectile.onProjectileLifeEnd.add(() => {
               EffectService.playAtPosition("133276", ball.worldTransform.position);
           });

           // Add a 'LAUNCH' event listener sent by the client and shoot the ball upwards.
           Event.addClientListener("LAUNCH", async (player: Player) => {
               // Set the owner as a Player character.
               projectile.owner = player.character;
               projectile.launch(new Vector(1, 0, 1));
           });

           // Add the "PAUSE" event listener sent by the client, which will pause the movement of the projectile and print the status.
           Event.addClientListener("PAUSE", async (player: Player) => {
               projectile.pause();
               console.log("Projectile status " + projectile.status);
           });

           // Add a "RESUME" event listener sent by the client to restore the motion of the projectile and print its status.
           Event.addClientListener("RESUME", async (player: Player) => {
               projectile.resume();
               console.log("Projectile status " + projectile.status);
           });
       }

       // The following logic is executed on the client side
       if(SystemUtil.isClient()) {
           // Add a key method: press key "1" to send a "LAUNCH" event to the server and launch the ball
           InputUtil.onKeyDown(Keys.One, () => {
               Event.dispatchToServer("LAUNCH");
           });

           // Add a key method: press key "2" to send a "PAUSE" event to the server and launch the ball
           InputUtil.onKeyDown(Keys.Two, () => {
               Event.dispatchToServer("PAUSE");
           });

           // Add a key method: press key "3" to send a "RESUME" event to the server and launch the ball
           InputUtil.onKeyDown(Keys.Three, () => {
               Event.dispatchToServer("RESUME");
           });
       }
   }
}
@Component
export default class Example_ProjectileMovement_Launch extends Script {

   protected async onStart(): Promise<void> {

       // The following logic is executed on the server side
       if(SystemUtil.isServer()) {

           // Asynchronously generate a sphere at world coordinates (200, 0, 25)
           let ball = await GameObject.asyncSpawn("84121") as Model;
           ball.worldTransform.position = new Vector(200, 0, 25);
           ball.name = "ball";
           ball.setCollision(CollisionStatus.QueryCollisionOnly);

           // Asynchronously generate a wall at world coordinates (1000, 0, 0)
           let wall = await GameObject.asyncSpawn("197386") as Model;
           wall.worldTransform.position = new Vector(1000, 0, 0);
           wall.worldTransform.scale = new Vector(1, 5, 5);
           wall.name = "wall";

           // Create a projectile.
           let projectile = new ProjectileMovement(ball);

           // Set the initial launch speed to 1500.
           projectile.initialSpeed = 1500;
           // Set gravity scaling to 1.
           projectile.gravityScale = 1;
           // Set the direction of the rotation of the projectile to follow the speed.
           projectile.isRotationFollowsVelocity = true;
           // Set the ratio of collision maintenance speed of projectile to 0.4.
           projectile.speedRetention = 0.4;

           // Bind a function to the hit delegate, print the hit information: character X launches object Y hits object Z, and play a hit effect.
           projectile.onProjectileHit.add((hitGameObject, HitResult) => {
               console.log( "Projectile " + projectile.getRelatedGameObject().name + " thrown by Character " + projectile.owner.displayName + " hits the " + hitGameObject.name);
               EffectService.playAtPosition("99599", HitResult.impactPoint);
           });

           // Bind a function to the end of life delegate of the projectile, and play a destroy effect.
           projectile.onProjectileLifeEnd.add(() => {
               EffectService.playAtPosition("133276", ball.worldTransform.position);
           });

           // Add a 'LAUNCH' event listener sent by the client and shoot the ball upwards.
           Event.addClientListener("LAUNCH", async (player: Player) => {
               // Set the owner as a Player character.
               projectile.owner = player.character;
               projectile.launch(new Vector(1, 0, 1));
           });

           // Add the "PAUSE" event listener sent by the client, which will pause the movement of the projectile and print the status.
           Event.addClientListener("PAUSE", async (player: Player) => {
               projectile.pause();
               console.log("Projectile status " + projectile.status);
           });

           // Add a "RESUME" event listener sent by the client to restore the motion of the projectile and print its status.
           Event.addClientListener("RESUME", async (player: Player) => {
               projectile.resume();
               console.log("Projectile status " + projectile.status);
           });
       }

       // The following logic is executed on the client side
       if(SystemUtil.isClient()) {
           // Add a key method: press key "1" to send a "LAUNCH" event to the server and launch the ball
           InputUtil.onKeyDown(Keys.One, () => {
               Event.dispatchToServer("LAUNCH");
           });

           // Add a key method: press key "2" to send a "PAUSE" event to the server and launch the ball
           InputUtil.onKeyDown(Keys.Two, () => {
               Event.dispatchToServer("PAUSE");
           });

           // Add a key method: press key "3" to send a "RESUME" event to the server and launch the ball
           InputUtil.onKeyDown(Keys.Three, () => {
               Event.dispatchToServer("RESUME");
           });
       }
   }
}

resume ​

• resume(): void other

Continue exercising and switch from Ready state to Launched state

Precautions

Corresponding to the pause method, the object that has not been emitted will not move when call

Example usage: Create a script and place it in the object bar. Copy and save the following code "Instance-PProjectileMovement_Launch" in the script. Run the game, and a ball for firing and a wall for collision will be generated in the scene. Bind the function to the delegate of the event corresponding to the emitter. Press button "1" to launch the ball; press button "2" to temporarily stop the ball's movement; press button "3" to resume the ball's movement; set the object code as follows:

ts
@Component
export default class Example_ProjectileMovement_Launch extends Script {

   protected async onStart(): Promise<void> {

       // The following logic is executed on the server side
       if(SystemUtil.isServer()) {

           // Asynchronously generate a sphere at world coordinates (200, 0, 25)
           let ball = await GameObject.asyncSpawn("84121") as Model;
           ball.worldTransform.position = new Vector(200, 0, 25);
           ball.name = "ball";
           ball.setCollision(CollisionStatus.QueryCollisionOnly);

           // Asynchronously generate a wall at world coordinates (1000, 0, 0)
           let wall = await GameObject.asyncSpawn("197386") as Model;
           wall.worldTransform.position = new Vector(1000, 0, 0);
           wall.worldTransform.scale = new Vector(1, 5, 5);
           wall.name = "wall";

           // Create a projectile.
           let projectile = new ProjectileMovement(ball);

           // Set the initial launch speed to 1500.
           projectile.initialSpeed = 1500;
           // Set gravity scaling to 1.
           projectile.gravityScale = 1;
           // Set the direction of the rotation of the projectile to follow the speed.
           projectile.isRotationFollowsVelocity = true;
           // Set the ratio of collision maintenance speed of projectile to 0.4.
           projectile.speedRetention = 0.4;

           // Bind a function to the hit delegate, print the hit information: character X launches object Y hits object Z, and play a hit effect.
           projectile.onProjectileHit.add((hitGameObject, HitResult) => {
               console.log( "Projectile " + projectile.getRelatedGameObject().name + " thrown by Character " + projectile.owner.displayName + " hits the " + hitGameObject.name);
               EffectService.playAtPosition("99599", HitResult.impactPoint);
           });

           // Bind a function to the end of life delegate of the projectile, and play a destroy effect.
           projectile.onProjectileLifeEnd.add(() => {
               EffectService.playAtPosition("133276", ball.worldTransform.position);
           });

           // Add a 'LAUNCH' event listener sent by the client and shoot the ball upwards.
           Event.addClientListener("LAUNCH", async (player: Player) => {
               // Set the owner as a Player character.
               projectile.owner = player.character;
               projectile.launch(new Vector(1, 0, 1));
           });

           // Add the "PAUSE" event listener sent by the client, which will pause the movement of the projectile and print the status.
           Event.addClientListener("PAUSE", async (player: Player) => {
               projectile.pause();
               console.log("Projectile status " + projectile.status);
           });

           // Add a "RESUME" event listener sent by the client to restore the motion of the projectile and print its status.
           Event.addClientListener("RESUME", async (player: Player) => {
               projectile.resume();
               console.log("Projectile status " + projectile.status);
           });
       }

       // The following logic is executed on the client side
       if(SystemUtil.isClient()) {
           // Add a key method: press key "1" to send a "LAUNCH" event to the server and launch the ball
           InputUtil.onKeyDown(Keys.One, () => {
               Event.dispatchToServer("LAUNCH");
           });

           // Add a key method: press key "2" to send a "PAUSE" event to the server and launch the ball
           InputUtil.onKeyDown(Keys.Two, () => {
               Event.dispatchToServer("PAUSE");
           });

           // Add a key method: press key "3" to send a "RESUME" event to the server and launch the ball
           InputUtil.onKeyDown(Keys.Three, () => {
               Event.dispatchToServer("RESUME");
           });
       }
   }
}
@Component
export default class Example_ProjectileMovement_Launch extends Script {

   protected async onStart(): Promise<void> {

       // The following logic is executed on the server side
       if(SystemUtil.isServer()) {

           // Asynchronously generate a sphere at world coordinates (200, 0, 25)
           let ball = await GameObject.asyncSpawn("84121") as Model;
           ball.worldTransform.position = new Vector(200, 0, 25);
           ball.name = "ball";
           ball.setCollision(CollisionStatus.QueryCollisionOnly);

           // Asynchronously generate a wall at world coordinates (1000, 0, 0)
           let wall = await GameObject.asyncSpawn("197386") as Model;
           wall.worldTransform.position = new Vector(1000, 0, 0);
           wall.worldTransform.scale = new Vector(1, 5, 5);
           wall.name = "wall";

           // Create a projectile.
           let projectile = new ProjectileMovement(ball);

           // Set the initial launch speed to 1500.
           projectile.initialSpeed = 1500;
           // Set gravity scaling to 1.
           projectile.gravityScale = 1;
           // Set the direction of the rotation of the projectile to follow the speed.
           projectile.isRotationFollowsVelocity = true;
           // Set the ratio of collision maintenance speed of projectile to 0.4.
           projectile.speedRetention = 0.4;

           // Bind a function to the hit delegate, print the hit information: character X launches object Y hits object Z, and play a hit effect.
           projectile.onProjectileHit.add((hitGameObject, HitResult) => {
               console.log( "Projectile " + projectile.getRelatedGameObject().name + " thrown by Character " + projectile.owner.displayName + " hits the " + hitGameObject.name);
               EffectService.playAtPosition("99599", HitResult.impactPoint);
           });

           // Bind a function to the end of life delegate of the projectile, and play a destroy effect.
           projectile.onProjectileLifeEnd.add(() => {
               EffectService.playAtPosition("133276", ball.worldTransform.position);
           });

           // Add a 'LAUNCH' event listener sent by the client and shoot the ball upwards.
           Event.addClientListener("LAUNCH", async (player: Player) => {
               // Set the owner as a Player character.
               projectile.owner = player.character;
               projectile.launch(new Vector(1, 0, 1));
           });

           // Add the "PAUSE" event listener sent by the client, which will pause the movement of the projectile and print the status.
           Event.addClientListener("PAUSE", async (player: Player) => {
               projectile.pause();
               console.log("Projectile status " + projectile.status);
           });

           // Add a "RESUME" event listener sent by the client to restore the motion of the projectile and print its status.
           Event.addClientListener("RESUME", async (player: Player) => {
               projectile.resume();
               console.log("Projectile status " + projectile.status);
           });
       }

       // The following logic is executed on the client side
       if(SystemUtil.isClient()) {
           // Add a key method: press key "1" to send a "LAUNCH" event to the server and launch the ball
           InputUtil.onKeyDown(Keys.One, () => {
               Event.dispatchToServer("LAUNCH");
           });

           // Add a key method: press key "2" to send a "PAUSE" event to the server and launch the ball
           InputUtil.onKeyDown(Keys.Two, () => {
               Event.dispatchToServer("PAUSE");
           });

           // Add a key method: press key "3" to send a "RESUME" event to the server and launch the ball
           InputUtil.onKeyDown(Keys.Three, () => {
               Event.dispatchToServer("RESUME");
           });
       }
   }
}

setRelatedGameObject ​

• setRelatedGameObject(value): void other

Set up a new associated logical object

Parameters ​

value GameObjectNew associated logical object. After setting, moving the component will regenerate and attach to this object

Usage example: create a script and place it in the object bar. copy the following "Example_ProjectileMovement" code in the script and save it. Run the game. Five balls will be generated in the scene for launching. Bind the function to the delegate of the event corresponding to the emitter. Press button "1" to launch the ball object associated with the projectile. Press button "2" to switch the ball object associated with the projectile and delete the previous one. Note that you need to wait for the ball to stop before switching, otherwise the ball object associated with the projectile will be switched in advance; set the object code as follows:

ts
@Component
export default class Example_ProjectileMovement extends Script {

   protected async onStart(): Promise<void> {

       // The following logic is executed on the server side
       if(SystemUtil.isServer()) {

           // Create a model array balls and identify curBall.
           let balls = new Array<Model>();
           let curBall = 0;

           // Generate 5 balls asynchronously ahead and place them in the array of balls.
           for (let i = 0;
i < 5;
i++) {
               let ball = await GameObject.asyncSpawn("84121") as Model;
               ball.worldTransform.position = new Vector(200, i * 100, 25);
               ball.name = "ball" + i;
               ball.setCollision(CollisionStatus.QueryCollisionOnly);
               balls.push(ball);
           }

           // Create a projectile.
           let projectile = new ProjectileMovement(balls[curBall]);

           // Set the initial launch speed to 1000.
           projectile.initialSpeed = 1000;

           // Bind a function to the hit delegate. When the hit object is a target, play a hit effect. After 0.5s, delete the target.
           projectile.onProjectileHit.add((hitGameObject, HitResult) => {
               EffectService.playAtPosition("99599", HitResult.impactPoint, {scale: new Vector(5, 5, 5)});
           });

           // Add the "LAUNCH" event listener sent by the client and emit the ball to the front right.
           Event.addClientListener("LAUNCH", async (player: Player) => {
               projectile.launch(new Vector(1, 1, 1));
           });

           // Add the "DESTROY" event listener sent by the client, delete the sphere object from the array, and switch the objects associated with the projectile.
           Event.addClientListener("DESTROY", async (player: Player) => {
               console.error("DESTROY");
               let deleteBall = projectile.getRelatedGameObject() as Model;
               let deleteIndex = balls.indexOf(deleteBall);
               balls.splice(deleteIndex, 1);
               if(balls.length > 0) {
                   curBall = (deleteIndex) % balls.length;
                   projectile.setRelatedGameObject(balls[curBall]);
                   deleteBall.destroy();
               } else {
                   projectile.destroy(true);
               }
           });
       }

       // The following logic is executed on the client side
       if(SystemUtil.isClient()) {
           // Add a button method: Press button "1" to send a "LAUNCH" event to the server and launch a ball.
           InputUtil.onKeyDown(Keys.One, () => {
               Event.dispatchToServer("LAUNCH");
           });

           // Add a key method: press key "2", send a "DESTROY" event to the server, switch to the next sphere and delete the previous one.
           InputUtil.onKeyDown(Keys.Two, () => {
               Event.dispatchToServer("DESTROY");
           });
       }
   }
}
@Component
export default class Example_ProjectileMovement extends Script {

   protected async onStart(): Promise<void> {

       // The following logic is executed on the server side
       if(SystemUtil.isServer()) {

           // Create a model array balls and identify curBall.
           let balls = new Array<Model>();
           let curBall = 0;

           // Generate 5 balls asynchronously ahead and place them in the array of balls.
           for (let i = 0;
i < 5;
i++) {
               let ball = await GameObject.asyncSpawn("84121") as Model;
               ball.worldTransform.position = new Vector(200, i * 100, 25);
               ball.name = "ball" + i;
               ball.setCollision(CollisionStatus.QueryCollisionOnly);
               balls.push(ball);
           }

           // Create a projectile.
           let projectile = new ProjectileMovement(balls[curBall]);

           // Set the initial launch speed to 1000.
           projectile.initialSpeed = 1000;

           // Bind a function to the hit delegate. When the hit object is a target, play a hit effect. After 0.5s, delete the target.
           projectile.onProjectileHit.add((hitGameObject, HitResult) => {
               EffectService.playAtPosition("99599", HitResult.impactPoint, {scale: new Vector(5, 5, 5)});
           });

           // Add the "LAUNCH" event listener sent by the client and emit the ball to the front right.
           Event.addClientListener("LAUNCH", async (player: Player) => {
               projectile.launch(new Vector(1, 1, 1));
           });

           // Add the "DESTROY" event listener sent by the client, delete the sphere object from the array, and switch the objects associated with the projectile.
           Event.addClientListener("DESTROY", async (player: Player) => {
               console.error("DESTROY");
               let deleteBall = projectile.getRelatedGameObject() as Model;
               let deleteIndex = balls.indexOf(deleteBall);
               balls.splice(deleteIndex, 1);
               if(balls.length > 0) {
                   curBall = (deleteIndex) % balls.length;
                   projectile.setRelatedGameObject(balls[curBall]);
                   deleteBall.destroy();
               } else {
                   projectile.destroy(true);
               }
           });
       }

       // The following logic is executed on the client side
       if(SystemUtil.isClient()) {
           // Add a button method: Press button "1" to send a "LAUNCH" event to the server and launch a ball.
           InputUtil.onKeyDown(Keys.One, () => {
               Event.dispatchToServer("LAUNCH");
           });

           // Add a key method: press key "2", send a "DESTROY" event to the server, switch to the next sphere and delete the previous one.
           InputUtil.onKeyDown(Keys.Two, () => {
               Event.dispatchToServer("DESTROY");
           });
       }
   }
}

setVelocity ​

• setVelocity(v): void other

Set current speed

Parameters ​

v Vectorspeed

Precautions

Can be called in both Launched and Ready states

Usage example: create a script and place it in the object bar. copy the following "Example_ProjectileMovement" code in the script and save it to run the game. Press key "1" to launch a rocket. The setting object code is as follows:

ts
@Component
export default class Example_ProjectileMovement extends Script {

   protected async onStart(): Promise<void> {

       // The following logic is executed on the server side
       if(SystemUtil.isServer()) {

           // Generate a rocket model in r (2000, 0, 0).
           let rocket = await GameObject.asyncSpawn("162807") as Model;
           rocket.worldTransform.position = new Vector(2000, 0, 0);

           // Change the collision status of the rocket to no collision
           rocket.setCollision(CollisionStatus.Off);

           // Create a projectile.
           let projectile = new ProjectileMovement(rocket);

           // Set the initial launch speed to 1.
           projectile.initialSpeed = 1;
           // Set the maximum speed to 1000.
           projectile.maxSpeed = 1000;
           // Set the launch acceleration to 200
           projectile.acceleration = 200;
           // Set gravity scaling to 0.
           projectile.gravityScale = 0;
           // Set the rotation of the projectile not to follow the speed direction.
           projectile.isRotationFollowsVelocity = false;
           // Set the movement time of projectile to 10 seconds.
           projectile.lifeSpan = 10;

           // Add a 'LAUNCH' event listener sent by the client and launch the rocket upwards.
           Event.addClientListener("LAUNCH", async (player: Player) => {
               projectile.launch(new Vector(0, 0, 1));
               // Broadcast client to mount rocket tail flame special effects
               Event.dispatchToAllClient("TAIL", rocket.gameObjectId);
               // Every 0.1 seconds, the current speed of the rocket will be broadcasted to the client
               let scaleInterval = TimeUtil.setInterval(() => {
                   if(projectile.getVelocity().length > 999) {
                       projectile.setVelocity(Vector.zero);
                       TimeUtil.clearInterval(scaleInterval);
                       rocket.worldTransform.position = new Vector(2000, 0, 0);
                   }
                   Event.dispatchToAllClient("SCALING", rocket.gameObjectId, projectile.getVelocity());
               }, 0.1);
           });
       }

       // The following logic is executed on the client side
       if(SystemUtil.isClient()) {
           // Add a key method: press key "1" to send a "LAUNCH" event to the server and launch the rocket
           InputUtil.onKeyDown(Keys.One, () => {
               Event.dispatchToServer("LAUNCH");
           });

           // Add a "TAIL" event listener sent by the server to mount the rocket's tail flame.
           Event.addServerListener("TAIL", async (rocketId: string) => {
               let rocket = await GameObject.asyncFindGameObjectById(rocketId);
               if(typeof(rocket.getChildByName("tail")) != "undefined") {
                   return;
               }
               let tail = await GameObject.asyncSpawn("144098") as Effect;
               tail.name = "tail";
               tail.parent = rocket;
               tail.localTransform.position = Vector.zero;
           });

           // Add the "SCALING" event listener sent by the server, and scale the tail flame according to the speed
           Event.addServerListener("SCALING", async (rocketId: string, velocity: Vector) => {
               let rocket = await GameObject.asyncFindGameObjectById(rocketId);
               let tail = rocket.getChildByName("tail");
               if(tail) {
                   tail.worldTransform.scale = Vector.one.multiply(velocity.length / 250);
               }
           });
       }
   }
}
@Component
export default class Example_ProjectileMovement extends Script {

   protected async onStart(): Promise<void> {

       // The following logic is executed on the server side
       if(SystemUtil.isServer()) {

           // Generate a rocket model in r (2000, 0, 0).
           let rocket = await GameObject.asyncSpawn("162807") as Model;
           rocket.worldTransform.position = new Vector(2000, 0, 0);

           // Change the collision status of the rocket to no collision
           rocket.setCollision(CollisionStatus.Off);

           // Create a projectile.
           let projectile = new ProjectileMovement(rocket);

           // Set the initial launch speed to 1.
           projectile.initialSpeed = 1;
           // Set the maximum speed to 1000.
           projectile.maxSpeed = 1000;
           // Set the launch acceleration to 200
           projectile.acceleration = 200;
           // Set gravity scaling to 0.
           projectile.gravityScale = 0;
           // Set the rotation of the projectile not to follow the speed direction.
           projectile.isRotationFollowsVelocity = false;
           // Set the movement time of projectile to 10 seconds.
           projectile.lifeSpan = 10;

           // Add a 'LAUNCH' event listener sent by the client and launch the rocket upwards.
           Event.addClientListener("LAUNCH", async (player: Player) => {
               projectile.launch(new Vector(0, 0, 1));
               // Broadcast client to mount rocket tail flame special effects
               Event.dispatchToAllClient("TAIL", rocket.gameObjectId);
               // Every 0.1 seconds, the current speed of the rocket will be broadcasted to the client
               let scaleInterval = TimeUtil.setInterval(() => {
                   if(projectile.getVelocity().length > 999) {
                       projectile.setVelocity(Vector.zero);
                       TimeUtil.clearInterval(scaleInterval);
                       rocket.worldTransform.position = new Vector(2000, 0, 0);
                   }
                   Event.dispatchToAllClient("SCALING", rocket.gameObjectId, projectile.getVelocity());
               }, 0.1);
           });
       }

       // The following logic is executed on the client side
       if(SystemUtil.isClient()) {
           // Add a key method: press key "1" to send a "LAUNCH" event to the server and launch the rocket
           InputUtil.onKeyDown(Keys.One, () => {
               Event.dispatchToServer("LAUNCH");
           });

           // Add a "TAIL" event listener sent by the server to mount the rocket's tail flame.
           Event.addServerListener("TAIL", async (rocketId: string) => {
               let rocket = await GameObject.asyncFindGameObjectById(rocketId);
               if(typeof(rocket.getChildByName("tail")) != "undefined") {
                   return;
               }
               let tail = await GameObject.asyncSpawn("144098") as Effect;
               tail.name = "tail";
               tail.parent = rocket;
               tail.localTransform.position = Vector.zero;
           });

           // Add the "SCALING" event listener sent by the server, and scale the tail flame according to the speed
           Event.addServerListener("SCALING", async (rocketId: string, velocity: Vector) => {
               let rocket = await GameObject.asyncFindGameObjectById(rocketId);
               let tail = rocket.getChildByName("tail");
               if(tail) {
                   tail.worldTransform.scale = Vector.one.multiply(velocity.length / 250);
               }
           });
       }
   }
}