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 GameObject | The new associated logical object will generate component for it |
---|---|
config? ProjectileMovementConfig | Batch 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 ​
• | • | ||||
---|---|---|---|---|---|
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 ​
| 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 ​
Implementation of ​ |
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]. Returns ​
| 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 ​
Implementation of ​ |
homingAcceleration ​
• | • | ||||
---|---|---|---|---|---|
Acceleration towards the target object (cm/s). Default: 10000. Range: [0, 10000]. Returns ​
| Acceleration towards the target object (cm/s). Default: 10000. Range: [0, 10000]. Parameters ​
Implementation of ​ |
homingTarget ​
• | • | ||||
---|---|---|---|---|---|
The target object tracked by the projectile will accelerate to the target when the target object is not empty. default: null。 Returns ​
| The target object tracked by the projectile will accelerate to the target when the target object is not empty. default: null。 Parameters ​
Implementation of ​ |
initialSpeed ​
• | • | ||||
---|---|---|---|---|---|
The initial movement speed of the projectile (cm/s), default: 5000, range: [110000], the setting will not take effect after launching Returns ​
| The initial movement speed of the projectile (cm/s), default: 5000, range: [110000], the setting will not take effect after launching Parameters ​
Implementation of ​ |
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。 Returns ​
| 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 ​
Implementation of ​ |
lifeSpan ​
• | • | ||||
---|---|---|---|---|---|
The maximum duration of the projectile's existence (s), 0 means there is no limit. Default: 10. Range: [0, 1000]. Returns ​
| The maximum duration of the projectile's existence (s), 0 means there is no limit. Default: 10. Range: [0, 1000]. Parameters ​
Implementation of ​ |
maxSpeed ​
• | • | ||||
---|---|---|---|---|---|
The maximum movement speed of the projectile (cm/s), 0 means there is no limit. Default: 0, range: [0100000]. Returns ​
| The maximum movement speed of the projectile (cm/s), 0 means there is no limit. Default: 0, range: [0100000]. Parameters ​
Implementation of ​ |
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]. Returns ​
| 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 ​
Implementation of ​ |
status ​
• |
---|
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? boolean | Whether 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:
@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 ​
GameObject | Related 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:
@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 Vector | Launch direction |
---|---|
density number | The 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 number | The 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 ​
Vector | Current 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:
@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 Vector | Emission 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:
@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:
@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:
@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 GameObject | New 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:
@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 Vector | speed |
---|
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:
@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);
}
});
}
}
}