Hot Weapon
INFO
It takes about 20 minutes to read this article
The editor provides the Hot Weapon object to help users customize firing weapons with unique experiences, creating a good combat experience. The Hot Weapon object includes six function modules to simulate the working mechanism of firing weapons: firing, reloading, aiming, loading, shoot accuracy, and recoil. Users can execute corresponding game logic when triggering corresponding events.
Hot Weapon Object
[Hot Weapon] is a functional framework for firing weapons,in which six functional modules,namely firing,reloading,aiming,loading,shoot accuracy and recoil are implemented to simulate the working mechanism of firing weapons. Developers can decide whether to enable these features and customize various attributes related to them. Different property configurations are used to simulate the performance of different types of weapons. Hot Weapon will trigger key events in the workflow to facilitate the user to accurately grasp the current working state of Hot Weapon and execute the corresponding game logic: muzzle effects, bullets, sound effects, etc. You can find [Hot Weapon] in "Gameplay Object" in "Local Asset Library."
Create Hot Weapon
Create by placing resource:
[Hot Weapon] can be placed in the scene as a game object. You can create an object by dragging the Hot Weapon into the Scene or Object Manager from the Gameplay Object in the Local Asset Library.
- Find [Hot Weapon] in the "Gameplay Object" column of "Local Asset Library"
- Drag an object into the scene or [Object Manager]
- Find the corresponding [Hot Weapon] object in the "Object" section of the "Object Manager" on the right and customize its property
Create from script:
Through the script, you can also pass the Hot Weapon resource ID in the Local Asset Library while the game is running: "HotWeapon" dynamically generates a HotWeapon object to use. Create a new script file in the script directory under "Project Contents" and drag the script to the "Object" column in the "Object Manager." Selected script for editing, replace the onStart method in the script with the following sample code: Generate a Hot Weapon object asynchronously, start double-ended synchronization at (300,0,50), rotate at (0,0,0), and scale by (1,1,1). Print the gameObjectId of the generated Hot Weapon object.
protected async onStart(): Promise<void> {
if(SystemUtil.isServer()) {
let weapon = await GameObject.asyncSpawn("HotWeapon", {replicates: true, transform: new Transform(new Vector(300, 0, 50), Rotation.zero, Vector.one)}) as HotWeapon;
console.log("HotWeapon gameObjectId: " + weapon.gameObjectId);
}
}
protected async onStart(): Promise<void> {
if(SystemUtil.isServer()) {
let weapon = await GameObject.asyncSpawn("HotWeapon", {replicates: true, transform: new Transform(new Vector(300, 0, 50), Rotation.zero, Vector.one)}) as HotWeapon;
console.log("HotWeapon gameObjectId: " + weapon.gameObjectId);
}
}
TIP
[Hot Weapon] is a double-ended synchronization object, its working status and parameters of each function module are modified by the server as authority. At the same time, [Hot Weapon] encapsulates a large number of client interfaces to facilitate users to connect with UI operations.
Custom Hot Weapon
Fire Function:
Fire is a function that must be activated in the workflow of hot weapons. The function defines the attributes related to fire and provides the relevant API. The Fire function exists in the [Hot Weapon] object as a function component object: fireComponent
, through which we can define the weapon firing performance. Some attributes of fireComponent
can be configured in the Property Panel or read or written from code. The animationAssetId
property is used to specify the firing action. the fireMode
property is used to get the weapon's current firing mode (modification requires using the Hot Weapon API, see below). the fireInterval
property is used to set the firing interval. the clipSize
property is used to set the number of bullets in the magazine. the multipleShot
property is used to set the number of bullets fired in a single firing.
Some properties are dynamic and can only be read or written in code. The current Bullet
attribute is used to indicate the amount of ammunition left in the magazine.
Fire Action Binding: The action played when the hot weapon is fired (support library drag entry).
Fire Mode:
- Single-fire: Automatically cease fire after 1 launch per execution.
- Continuous fire: After firing [number of continuous fire] times, cease fire.
- Full Auto: Fires continuously each time fire is executed, until the ceasefire is manually invoked or the magazine bullet is 0.
Interval: Minimum interval between two bullets fired from a hot weapon
Magazine Capacity: Hot Weapon Magazine Size
Multiple shot: The number of splits per round
Screen Center Fire: Bullets are generated at the center of the camera.
- Fire Offset Adjustment: Bullet Generation Position Offset
// Get hot weapon object
let weapon = this.gameObject as HotWeapon;
// Set up firing animation 4167
weapon.fireComponent.animationAssetId = "4167";
// Get fire mode, change to fully automatic if not currently
if(weapon.fireComponent.fireMode != HotWeaponFireMode.FullAutomationFire) {
weapon.fireMode = HotWeaponFireMode.FullAutomationFire;
}
// Modify the transmit interval to 0.2s
weapon.fireComponent.fireInterval = 0.2;
// Modify magazine capacity to 10 (specified number of launches)
weapon.fireComponent.clipSize = 10;
// Modify the number of bullets fired to 5 (specify the number of bullets to be fired each time).
weapon.fireComponent.multipleShot = 5;
// Get hot weapon object
let weapon = this.gameObject as HotWeapon;
// Set up firing animation 4167
weapon.fireComponent.animationAssetId = "4167";
// Get fire mode, change to fully automatic if not currently
if(weapon.fireComponent.fireMode != HotWeaponFireMode.FullAutomationFire) {
weapon.fireMode = HotWeaponFireMode.FullAutomationFire;
}
// Modify the transmit interval to 0.2s
weapon.fireComponent.fireInterval = 0.2;
// Modify magazine capacity to 10 (specified number of launches)
weapon.fireComponent.clipSize = 10;
// Modify the number of bullets fired to 5 (specify the number of bullets to be fired each time).
weapon.fireComponent.multipleShot = 5;
TIP
The firing interval mainly controls the firing interval in [Burst Fire] and [Fully Automatic] mode. However, there is no shielding the firing operation, and the weapon will be re-fired if it is fired again at an interval. magazine capacity sets an upper limit for ammunition, and the number of magazine changes cannot exceed the magazine capacity. Also, be careful to distinguish between the number of bullets fired (how many times you can fire) and the number of bullets fired (number of bullets per round).
Fire Accuracy Function:
[Fire Accuracy] is an optional function in the hot weapon workflow. You can select whether to enable it on the property panel. The function defines attributes related to firing accuracy and provides related API. [ Firing Accuracy ] function exists in the Hot Weapon object as a function component object: accuracyOfFireComponent
, through which the developer can set the firing range, change the radius of the firing cone range, and adjust the firing accuracy. Some attributes of accuracyOfFireComponent
can be configured in the Property Panel or read or written from code. The defaultDispersionHalfAngle
attribute represents the default dispersive range. The maxDispersionHalfAngle
attribute represents the maximum dispersive range. The minDispersionHalfAngle
attribute represents the minimum dispersive range. The dispersionHalfAngleDecreaseSpeed
attribute represents the range shrink speed. The dispersionHalfAngleIncreaseSpeed
attribute represents the range expansion speed.
Some properties are dynamic and can only be read or written in code. The dispersionHalfAngleIncreaseSpeed
attribute represents the range expansion speed. The dispersionHalfAngleIncreasePerShot
attribute represents the expansion value of the radius of the bullet dispersive range after each fire.
- Dispersive Range Setting: Default radius of the dispersive range. When not firing, the range will move to the default.
- Maximum Dispersive Range: Maximum Dispersive Range Radius
- Minimum Dispersive Range: Minimum Dispersive Range Radius, provides the minimum anchor values for the two parameters above and can be used as a switch.
- Range shrinkage speed: The rate at which the dispersive range shrinks. Too large to expand the range.
- Speed of range expansion: refers to the speed of the spread of the range expansion, too large to make the range expansion too fast
// Get hot weapon object
let weapon = this.gameObject as HotWeapon;
weapon.accuracyOfFireComponent.defaultDispersionHalfAngle = 10;
weapon.accuracyOfFireComponent.maxDispersionHalfAngle = 20;
weapon.accuracyOfFireComponent.minDispersionHalfAngle = 1;
weapon.accuracyOfFireComponent.dispersionHalfAngleDecreaseSpeed = 10;
weapon.accuracyOfFireComponent.dispersionHalfAngleIncreaseSpeed = 10;
// Get hot weapon object
let weapon = this.gameObject as HotWeapon;
weapon.accuracyOfFireComponent.defaultDispersionHalfAngle = 10;
weapon.accuracyOfFireComponent.maxDispersionHalfAngle = 20;
weapon.accuracyOfFireComponent.minDispersionHalfAngle = 1;
weapon.accuracyOfFireComponent.dispersionHalfAngleDecreaseSpeed = 10;
weapon.accuracyOfFireComponent.dispersionHalfAngleIncreaseSpeed = 10;
TIP
Shrinkage too fast will prevent the range from spreading. With accuracy, the bullet will be randomly offset within the conical range of the current walking Angle. The values of the dispersive range are typically used to calculate the reticle UI range. The center of the range is the center of the screen.
Aiming Function:
[aim] is an optional feature in the hot weapon workflow. You can select whether to enable it on the property panel. Aiming properties are defined in this feature and associated API are provided. The aiming function exists in the Hot Weapon object as a function component object: aimComponent
, through which the developer can modify the camera distance during aiming and switch the aiming state.
Aiming Mode:
Third-person:
Camera Distance Adjustment: Camera rod length changes when aiming
// Get hot weapon object
let weapon = this.gameObject as HotWeapon;
// Set camera distance when aiming
weapon.aimComponent.cameraOffsetDistanceInThirdPersonMode = 300
// enable aiming
weapon.aimComponent.enableAiming(true);
// Get hot weapon object
let weapon = this.gameObject as HotWeapon;
// Set camera distance when aiming
weapon.aimComponent.cameraOffsetDistanceInThirdPersonMode = 300
// enable aiming
weapon.aimComponent.enableAiming(true);
TIP
Do not delete the [Hot Weapon] object during camera zoom caused by aiming switch or it will report an error.
Loading Function:
[Loaded] is an optional function in the hot weapon workflow. You can select whether to enable it on the property panel. This function defines the properties related to loading and provides the associated API. The Loading function exists in the Hot Weapon object as a function component object: loadComponent
, through which developers can set loading performance. The “animationAssetId”
property is used to specify the loading action. the “loadDuration”
property is used to set the loading time. the “loadAfterFireEnabled”
property is used to set whether each firing requires loading (shotgun, sniper).
- Loaded Action Binding: Plays bound actions when a hot weapon is loaded (supports asset library drag).
- Loading Time: The time when the loading action is completed.
- Load After Launch: Check to load automatically after each launch (default is to reload after reloading).
// Get hot weapon object
let weapon = this.gameObject as HotWeapon;
// Set up loaded animation 80482
weapon.loadComponent.animationAssetId = "80482";
// Set the loading time to 0.5s
weapon.loadComponent.loadDuration = 0.5;
// Set loading to true after launch
weapon.loadComponent.loadAfterFireEnabled = true;
// Get hot weapon object
let weapon = this.gameObject as HotWeapon;
// Set up loaded animation 80482
weapon.loadComponent.animationAssetId = "80482";
// Set the loading time to 0.5s
weapon.loadComponent.loadDuration = 0.5;
// Set loading to true after launch
weapon.loadComponent.loadAfterFireEnabled = true;
TIP
Each reload automatically reloads and the reloading time is too short to allow the animation to play. Furthermore,loading time is independent of animation playback rate and loading animation can be interrupted by other animations due to animation mechanism.
Reloading Function:
[Reloading] is an optional function in the hot weapon workflow. You can select whether to enable it on the property panel. Attributes related to bullet reloading are defined and interfaces are provided. The bullet reloading function exists in the Hot Weapon object as a function component object: reloadComponent
, through which developers can set bullet reloading performance. The “animationAssetId”
attribute is used to specify the reload action. the “reloadDuration”
attribute is used to set the reload time.
- Bind Reloading Action: Player character actions played when the weapon reloads (via asset library drag)
- Reload Time: Time required for weapon to trigger reload and end of reload.
// Get hot weapon object
let weapon = this.gameObject as HotWeapon;
// Set reloading animation 4170
weapon.reloadComponent.animationAssetId = "4170";
// Set the reload time to 0.5s
weapon.reloadComponent.reloadDuration = 0.5;
// Get hot weapon object
let weapon = this.gameObject as HotWeapon;
// Set reloading animation 4170
weapon.reloadComponent.animationAssetId = "4170";
// Set the reload time to 0.5s
weapon.reloadComponent.reloadDuration = 0.5;
TIP
Too short a reload time will prevent the animation from playing. In addition,the reload time is independent of the animation playback rate and because of the animation mechanism,the reload animation can be interrupted by other animations.
Recoil Function:
[Recoil] is an optional function in the Hot Weapon workflow. You can select whether to enable it on the property panel. Recoil-related properties are defined and interfaces are provided. The recoil function exists in the Hot Weapon object as a function component object: the recoilForceComponent
, through which developers can. Some attributes of accuracyOfFireComponent
can be configured in the Property Panel or read or written from code. The defaultDispersionHalfAngle
attribute represents the default dispersive range. The maxDispersionHalfAngle
attribute represents the maximum dispersive range. The minDispersionHalfAngle
attribute represents the minimum dispersive range. The dispersionHalfAngleDecreaseSpeed
attribute represents the range shrink speed. The dispersionHalfAngleIncreaseSpeed
attribute represents the range expansion speed.
Some properties are dynamic and can only be read or written in code. The dispersionHalfAngleIncreaseSpeed
attribute represents the range expansion speed. The dispersionHalfAngleIncreasePerShot
attribute represents the expansion value of the radius of the bullet dispersive range after each fire.
- Horizontal Offset Minimum/Maximum: Each time a hot weapon is fired, the camera rotates horizontally based on the camera position at the time of firing. The offset value is random within a set interval.
- Vertical Offset Minimum/Maximum: Each time a hot weapon is fired, the camera will rotate vertically based on the camera position at the time of firing. The offset value will be random within a set interval.
- Horizontal Shake Minimum/Maximum: When a hot weapon is fired, the camera will rotate horizontally based on the camera position at the time of firing. After a single firing, the camera will return to the position after horizontal offset, i.e., the camera's horizontal shake is a manifestation that will not affect the weapon's final position.
- Vertical Shake Minimum/Maximum: When a hot weapon is fired, the camera rotates vertically based on the camera position at the time of firing. After a single firing, the camera returns to the position after vertical deflection, i.e., the camera's vertical shake is a manifestation that will not affect the final position of the weapon.
// Get hot weapon object
let weapon = this.gameObject as HotWeapon;
// Shake related properties
weapon.recoilForceComponent.minHorizontalOffset = -0.5;
weapon.recoilForceComponent.maxHorizontalOffset = 0.5;
weapon.recoilForceComponent.minVerticalOffset = -0.3;
weapon.recoilForceComponent.maxVerticalOffset = -0.2;
// Offset attribute
weapon.recoilForceComponent.minHorizontalJitter = -0.7;
weapon.recoilForceComponent.maxHorizontalJitter = 0.7;
weapon.recoilForceComponent.minVerticalJitter = -0.8;
weapon.recoilForceComponent.maxVerticalJitter = 0.8;
// Get hot weapon object
let weapon = this.gameObject as HotWeapon;
// Shake related properties
weapon.recoilForceComponent.minHorizontalOffset = -0.5;
weapon.recoilForceComponent.maxHorizontalOffset = 0.5;
weapon.recoilForceComponent.minVerticalOffset = -0.3;
weapon.recoilForceComponent.maxVerticalOffset = -0.2;
// Offset attribute
weapon.recoilForceComponent.minHorizontalJitter = -0.7;
weapon.recoilForceComponent.maxHorizontalJitter = 0.7;
weapon.recoilForceComponent.minVerticalJitter = -0.8;
weapon.recoilForceComponent.maxVerticalJitter = 0.8;
Use Hot Weapon
Get Hot Weapon Object
[Hot Weapon] objects under [Objects] in [Object Manager]:
Use the asyncFindGameObjectById
interface to get:
- After selecting the [Hot Weapon] object, right-click on [Copy Object ID] to get its gameObjectId. Note here the distinction between the gameObjectId of the Hot Weapon resource and the gameObjectId of the Hot Weapon object.
- Drag the script under Object Manager and replace the
onStart
method in the script with the following code: The code will asynchronously find the object with the corresponding ID to receive as a Hot Weapon object.
protected async onStart(): Promise<void> {
if(SystemUtil.isServer()) {
let weapon = await GameObject.asyncFindGameObjectById("1CAD6351") as HotWeapon;
console.log("weapon gameObjectId " + weapon.gameObjectId);
}
}
protected async onStart(): Promise<void> {
if(SystemUtil.isServer()) {
let weapon = await GameObject.asyncFindGameObjectById("1CAD6351") as HotWeapon;
console.log("weapon gameObjectId " + weapon.gameObjectId);
}
}
Use script mount to obtain:
- Mount the script under the Hot Weapon object
- Add the following code to the script's
onStart
method: Code to get the script's mounted object and receive it as a Hot Weapon object
let weapon = this.gameObject as HotWeapon;
let weapon = this.gameObject as HotWeapon;
Dynamically generated Hot Weapon objects:
Replace the onStart
method in the script with the following sample code: The sample code asynchronously generates a corresponding Hot Weapon object by passing the Hot Weapon resource ID "HotWeapon" to the asyncSpawn
interface on the client side.
protected async onStart(): Promise<void> {
if(SystemUtil.isServer()) {
let weapon = await GameObject.asyncSpawn("HotWeapon", {replicates: true, transform: new Transform(new Vector(300, 0, 50), Rotation.zero, Vector.one)}) as HotWeapon;
console.log("weapon gameObjectId: " + weapon.gameObjectId);
}
}
protected async onStart(): Promise<void> {
if(SystemUtil.isServer()) {
let weapon = await GameObject.asyncSpawn("HotWeapon", {replicates: true, transform: new Transform(new Vector(300, 0, 50), Rotation.zero, Vector.one)}) as HotWeapon;
console.log("weapon gameObjectId: " + weapon.gameObjectId);
}
}
Component Function Switch
[Hot Weapon] In addition to the firing function being an uncontrollable switch, other functions can be selectively turned on or off by the user. Component functions: reloading, loading, recoil, firing accuracy. Aiming needs to be activated to have the corresponding function. The corresponding flow will only be executed when the hot weapon is working. [Hot Weapon] activates all functions by default. recoilForceEnabled
attribute correspond to a recoil function switch; reloadEnabled
attribute corresponds to a bullet exchange function switch; loadEnabled
attribute correspond to a loaded function switch; accuracyOfFireEnabled
attribute corresponds to a firing accuracy function switch; aimEnabled
attribute corresponds to a aiming function switch;
// Get hot weapon object
let weapon = this.gameObject as HotWeapon;
// Operate the switches of each function component (the firing function is not operable and is activated by default).
weapon.aimEnabled = true;
weapon.loadEnabled = true;
weapon.reloadEnabled = true;
weapon.accuracyOfFireEnabled = true;
weapon.recoilForceEnabled = true;
// Get hot weapon object
let weapon = this.gameObject as HotWeapon;
// Operate the switches of each function component (the firing function is not operable and is activated by default).
weapon.aimEnabled = true;
weapon.loadEnabled = true;
weapon.reloadEnabled = true;
weapon.accuracyOfFireEnabled = true;
weapon.recoilForceEnabled = true;
Equip & Unload
[Hot Weapon] provides an interface for easy equipping and unloading. To use the Hot Weapon function, you need to call the equip
interface to equip the Hot Weapon object with a slot on the character. The Hot Weapon object refreshes its owner and is temporarily moved to the character slot. Unload the Hot Weapon to invoke the unequip
interface, and the Hot Weapon object loses its owner and is unbound from the character.
@Class
export default class NewScript extends Script {
// Hot Weapon Object
weapon: HotWeapon;
/** When the script is instanced, this function is called before the first frame is updated */
protected async onStart(): Promise<void> {
// Get hot weapon object with both ends
this.weapon = this.gameObject as HotWeapon;
console.log("this.weapon gameObjectId " + this.weapon.gameObjectId);
// Server
if(SystemUtil.isServer()) {
// Add server-side equip callback
this.weapon.onEquip.add(() => {
console.error("onEquippedServer")
});
// Add server-side offload callback
this.weapon.onUnequip.add(() => {
console.error("onUnequippedServer")
});
}
// Client
if(SystemUtil.isClient()) {
// Add client equipment callback
this.weapon.onEquip.add(() => {
console.error("onEquippedClient")
});
// Add client uninstall callback
this.weapon.onUnequip.add(() => {
console.error("onUnequippedClient")
});
// Add button method to equip hot weapon by pressing keyboard "E"
InputUtil.onKeyDown(Keys.E, async () => {
// Get the equipped character object
let chara Player.localPlayer.character;
// Call RPC function to equip server, pass character ID to server
this.equip_Server(chara.gameObjectId);
});
// Add button method to uninstall hot weapon by pressing keyboard "Q"
InputUtil.onKeyDown(Keys.Q, async () => {
this.weapon.unequip();
});
}
}
// Server-side RPC function: equip hot weapon
@RemoteFunction(Server)
private equip_Server(charaGameObjectId: string) {
// Equip the hot weapon object to the character's right hand slot after asynchronously finding the character and call the RPC function to equip all clients
GameObject.asyncFindGameObjectById(charaGameObjectId).then((chara: Character) => {
this.weapon.equip(chara, HumanoidSlotType.RightHand);
this.equip_Client(charagameObjectId);
});
}
// Client broadcasts RPC function: equip hot weapon
@RemoteFunction(Client, Multicast)
private equip_Client(charaGameObjectId: string) {
// Equip hot weapon objects to the character's right hand slot after asynchronously finding the character
GameObject.asyncFindGameObjectById(charaGameObjectId).then((chara: Character) => {
this.weapon.equip(chara, HumanoidSlotType.RightHand);
});
}
}
@Class
export default class NewScript extends Script {
// Hot Weapon Object
weapon: HotWeapon;
/** When the script is instanced, this function is called before the first frame is updated */
protected async onStart(): Promise<void> {
// Get hot weapon object with both ends
this.weapon = this.gameObject as HotWeapon;
console.log("this.weapon gameObjectId " + this.weapon.gameObjectId);
// Server
if(SystemUtil.isServer()) {
// Add server-side equip callback
this.weapon.onEquip.add(() => {
console.error("onEquippedServer")
});
// Add server-side offload callback
this.weapon.onUnequip.add(() => {
console.error("onUnequippedServer")
});
}
// Client
if(SystemUtil.isClient()) {
// Add client equipment callback
this.weapon.onEquip.add(() => {
console.error("onEquippedClient")
});
// Add client uninstall callback
this.weapon.onUnequip.add(() => {
console.error("onUnequippedClient")
});
// Add button method to equip hot weapon by pressing keyboard "E"
InputUtil.onKeyDown(Keys.E, async () => {
// Get the equipped character object
let chara Player.localPlayer.character;
// Call RPC function to equip server, pass character ID to server
this.equip_Server(chara.gameObjectId);
});
// Add button method to uninstall hot weapon by pressing keyboard "Q"
InputUtil.onKeyDown(Keys.Q, async () => {
this.weapon.unequip();
});
}
}
// Server-side RPC function: equip hot weapon
@RemoteFunction(Server)
private equip_Server(charaGameObjectId: string) {
// Equip the hot weapon object to the character's right hand slot after asynchronously finding the character and call the RPC function to equip all clients
GameObject.asyncFindGameObjectById(charaGameObjectId).then((chara: Character) => {
this.weapon.equip(chara, HumanoidSlotType.RightHand);
this.equip_Client(charagameObjectId);
});
}
// Client broadcasts RPC function: equip hot weapon
@RemoteFunction(Client, Multicast)
private equip_Client(charaGameObjectId: string) {
// Equip hot weapon objects to the character's right hand slot after asynchronously finding the character
GameObject.asyncFindGameObjectById(charaGameObjectId).then((chara: Character) => {
this.weapon.equip(chara, HumanoidSlotType.RightHand);
});
}
}
TIP
The equip
interface needs to be called on the server side, and the client side calls only to refresh the client's owner data. Note that this function needs to be called after the TS layer hot weapon construction is complete (use await, ready, or then). Note that the ammunition is still 0 after equipping, and requires reloading to fire normally. The unequip
interface can be called with both ends, and client calls will broadcast automatically.
Hot Weapon Owner
[Hot Weapon] provides a getCurrentOwner
interface for users to access its owner at any time. The interface returns a null value when there is no owner of the hot weapon.
// Get hot weapon object
let weapon = this.gameObject as HotWeapon;
// Print Hot Weapon Object Owner
console.log("weapon owner " + this.weapon.getCurrentOwner());
// Get hot weapon object
let weapon = this.gameObject as HotWeapon;
// Print Hot Weapon Object Owner
console.log("weapon owner " + this.weapon.getCurrentOwner());
TIP
The owner refreshes when the hot weapon equip is completed. Note that the owner attribute has not been refreshed by the client at the moment the server completes the equip. Do not use this interface when a client equip event is triggered (available on the server side). In addition, when a hot weapon is unloaded, the owner immediately becomes empty, so the owner visited is already empty when the unload event is triggered.
Fire & reload & load
The startFire
interface in [Hot Weapon] executes the firing operation. After calling, the [Hot Weapon] object enters the firing flow according to the settings of the [Fire] component. If the fire mode is fully automatic, you need to call the stopFire
interface to execute the ceasefire operation. Other modes will automatically cease fire after the number of fire attempts. The reload
interface performs reloading, and the user must enter a non-negative number to reload, but the final number of bullets will be limited by magazine capacity. The reload operation can be interrupted through the breakReload
interface. The load
interface performs loading operations, typically it is not actively invoked, and the loading process is automated, for example after reloading is completed or each launch is checked to load automatically. However, users can interrupt loading operations through the breakLoad
interface.
// Get hot weapon object
let weapon = this.gameObject as HotWeapon;
// Add button method, press the "F" key to fire
InputUtil.onKeyDown(Keys.F, async () => {
weapon.startFire();
});
// Add button method to lift keyboard "F" key to cease fire
InputUtil.onKeyUp(Keys.F, async () => {
weapon.stopFire();
});
// Add button method, press the "R" key to exchange bullets
InputUtil.onKeyDown(Keys.R, async () => {
// Replenish 10 rounds of ammunition and place the number of rounds at magazine capacity if magazine capacity limit is exceeded
weapon.reload(10);
});
// Add button method to break loading by pressing keyboard "B" key
InputUtil.onKeyUp(Keys.B, async () => {
weapon.breakLoad();
});
// Get hot weapon object
let weapon = this.gameObject as HotWeapon;
// Add button method, press the "F" key to fire
InputUtil.onKeyDown(Keys.F, async () => {
weapon.startFire();
});
// Add button method to lift keyboard "F" key to cease fire
InputUtil.onKeyUp(Keys.F, async () => {
weapon.stopFire();
});
// Add button method, press the "R" key to exchange bullets
InputUtil.onKeyDown(Keys.R, async () => {
// Replenish 10 rounds of ammunition and place the number of rounds at magazine capacity if magazine capacity limit is exceeded
weapon.reload(10);
});
// Add button method to break loading by pressing keyboard "B" key
InputUtil.onKeyUp(Keys.B, async () => {
weapon.breakLoad();
});
INFO
The startFire
and stopFire
interfaces are more like a trigger push that releases the trigger. Then execute the corresponding workflow according to the firing component settings of [Hot Weapon]. Duplicate execution is not supported for any of the above operations, i.e. it is not valid to call the relevant interface again when performing the corresponding operation. In addition, although these interfaces support double-ended calls, only calls initiated by the holder's client take effect when invoked by the client.
Hot Weapon Status
[Hot Weapon] comes in four states: Ready (Idle = 0), reloading (Reloading = 1), loading (Loading = 2), and firing (Firing = 3). The default status of the hot weapon is [Idle]. When firing starts to end, the status is [Firing]. When reloading is completed, the status is [Reloading].
enum HotWeaponState {
/** Ready for firing Non-shooter attitude */
Idle = 0,
/** Load magazine */
Reloading = 1,
/** Loaded */
Loading = 2,
/** Shot */
Firing = 3
}
// Turn onUpdate method
this.useUpdate = true;
// Get hot weapon object
let weapon = this.gameObject as HotWeapon;
// Print the current status of the hot weapon object per frame
protected onUpdate(dt: number): void {
console.log("weapon state " + weapon.getCurrentState(););
}
enum HotWeaponState {
/** Ready for firing Non-shooter attitude */
Idle = 0,
/** Load magazine */
Reloading = 1,
/** Loaded */
Loading = 2,
/** Shot */
Firing = 3
}
// Turn onUpdate method
this.useUpdate = true;
// Get hot weapon object
let weapon = this.gameObject as HotWeapon;
// Print the current status of the hot weapon object per frame
protected onUpdate(dt: number): void {
console.log("weapon state " + weapon.getCurrentState(););
}
TIP
Note that the true firing state duration is very short, i.e. 1-3 frames. During this time, [Hot Weapon] will be in [Firing] state, then it will return to the default state [Idle] waiting for the next firing. This is evident in fully automatic and continuous mode. However,it is often necessary to consider continuous fire or fully automatic fire as a whole state in actual development.In view of this need,[Hot Weapon] provides an extra isFiring
interface in fireComponent
to judge.
Common Interfaces
[Hot Weapon] Although it is only a functional framework, it does not implement specific weapon manifestations, but it provides corresponding interfaces to the functions that weapons generally need to implement, facilitating users to directly call the interfaces to obtain the return values needed to implement the functions. The getDefaultCrossHairSize
interface helps users get the size of the default reticle UI, and the getShootDirWithDispersion
interface helps users get the direction to fire towards the center of the screen after calculating the firing accuracy offset. In addition, because there are many hot weapon function components, the common clone interface cannot copy functions under hot weapon objects. CloneComponentsData
helps users copy data inside components.
Hot Weapon Event
The Hot Weapon body has two events: equipping onEquip
; unloading onUnequip
; and obtaining the Hot Weapon object. We can add delegate functions to the corresponding equip/unload events. When the Hot Weapon is equipped or unloaded, the corresponding event will be triggered and the delegate function will be executed.
[Fire Component] has 5 events: Fire starts onStartFire
; Fire ends onEndFireServer
; Continuous fire cycle ends onEndContinuousFire
; When [Hot Weapon] fires, corresponding events are triggered and delegate functions are executed.
[Recharge Component] There are 2 events: reload starts onStartReload
; reload ends onEndReload
; when [Hot Weapon] reloads, the corresponding event will be triggered and the delegate function will be executed.
[Loaded Component] has 4 events: loading starts onStartLoad
; loading ends onEndLoad
; when the [Hot Weapon] is loaded, the corresponding event will be triggered and the delegate function will be executed.
[Aiming Components] There are 4 events: aiming starts onStartAim
; aiming ends onEndAim
; when [Hot Weapon] executes aiming each time, the corresponding event will be triggered and the delegate function will be executed.
[Recoil Component] There are 2 events: Start Recoil onStartRecoil
; When [Hot Weapon] generates recoil each time it fires, it will trigger the corresponding event and execute the delegate function.
[Fire Precision Component] There is 1 event: Fire Precision Change onCurrentDispersionChange
. When the firing precision of [Hot Weapon] changes, the corresponding event will be triggered and the delegate function will be executed.
Replace the onStart
method in the script with the following sample code: The sample code adds corresponding callbacks to each end
// Get hot weapon object
let weapon = this.gameObject as HotWeapon;
// Add hot weapon callback to server
if(SystemUtil.isServer()) {
this.weapon.onEquip.add(() => {
// Logic to execute when the server's hot weapon is complete, such as updating player equipment data
console.log("onEquippedServer")
});
this.weapon.onUnequip.add(() => {
// Logic to execute when server-side hot weapon unload completes, e.g. updating player equipment data
console.log("onUnequippedServer")
});
this.weapon.fireComponent.onStartFire.add(() => {
// Logic that needs to be executed when the server-side hot weapon starts firing, such as generating a two-ended model as a bullet
console.log("onStartFireServer")
});
this.weapon.fireComponent.onEndFire.add(() => {
// logic that needs to be executed when the server-side hot weapon ends firing, such as making some weapon deformations
console.log("onEndFireServer")
});
this.weapon.fireComponent.onEndContinuousFire.add(() => {
// logic that needs to be executed at the end of a server-side hot weapon burst, such as making some weapon deformations
console.log("onEndContinuousFireServer")
});
this.weapon.reloadComponent.onStartReload.add(() => {
// Logic to execute when server-side hot weapons start reloading, e.g. updating player status
console.log("onStartReloadServer")
});
this.weapon.reloadComponent.onEndReload.add(() => {
// Logic to execute when the server-side hot weapon finishes reloading, e.g. updating player status
console.log("onEndReloadServer")
});
this.weapon.loadComponent.onStartLoad.add(() => {
// Logic to execute when server-side hot weapons start loading, e.g. updating player status
console.log("onStartLoadServer")
});
this.weapon.loadComponent.onEndLoad.add(() => {
// Logic to execute when the server hot weapon ends loading, e.g. updating the player status
console.log("onEndLoadServer")
});
this.weapon.aimComponent.onStartAim.add(() => {
// Logic to execute when the hot weapon starts aiming at the server, e.g. updating player status
console.log("onAimStartServer")
});
this.weapon.aimComponent.onEndAim.add(() => {
// Logic to execute when the server-side hot weapon ends aiming, e.g. updating the player status
console.log("onAimEndServer")
});
this.weapon.recoilForceComponent.onStartRecoil.add(() => {
// Logic to execute when the server-side hot weapon starts recoil, e.g. updating the weapon status
console.log("onStartRecoilForceServer")
});
}
// Client adds hot weapon callback
if(SystemUtil.isClient()) {
this.weapon.onEquip.add(() => {
// Logic to execute when the client's hot weapon is complete, such as playing an equipped sound effect
console.log("onEquippedClient")
});
this.weapon.onUnequip.add(() => {
// Logic that needs to be executed when the client hot weapon uninstall is complete, such as playing an equipped sound effect
console.log("onUnequippedClient")
});
this.weapon.fireComponent.onStartFire.add(() => {
// Logic to execute when the client's hot weapon starts firing, such as playing a firing sound effect
console.log("onStartFireClient")
});
this.weapon.fireComponent.onEndFire.add(() => {
// Logic that needs to be executed when the client hot weapon starts firing, e.g. update the UI interface on the number of bullets
console.log("onEndFireClient")
});
this.weapon.reloadComponent.onStartReload.add(() => {
// Logic to execute when the client hot weapon starts reloading, such as playing a reload sound effect
console.log("onStartReloadClient")
});
this.weapon.reloadComponent.onEndReload.add(() => {
// Logic that needs to be executed when the client-side hot weapon finishes reloading, e.g. update the UI interface on the number of bullets
console.log("onEndReloadClient")
});
this.weapon.loadComponent.onStartLoad.add(() => {
// Logic to execute when the client hot weapon starts loading, such as playing a loaded sound effect
console.log("onStartLoadClient")
});
this.weapon.loadComponent.onEndLoad.add(() => {
// logic that needs to be executed when the client hot weapon ends loading, such as playing an effect
console.log("onEndLoadClient")
});
this.weapon.aimComponent.onStartAim.add(() => {
// Logic to execute when the hot weapon starts aiming at the client, e.g. updating UI
console.log("onAimStartClient")
});
this.weapon.aimComponent.onEndAim.add(() => {
// Logic to execute when the client hot weapon ends aiming, e.g. updating UI
console.log("onAimEndClient")
});
this.weapon.recoilForceComponent.onStartRecoil.add(() => {
// Logic to execute when the client hot weapon starts recoil, e.g. update UI
console.log("onStartRecoilForceClient")
});
this.weapon.accuracyOfFireComponent.onCurrentDispersionChanged.add(() => {
// Logic to execute when the accuracy of the client's hot weapon fire changes, such as updating the reticle UI size.
console.log("onCurrentDispersionChangedClient")
});
}
// Get hot weapon object
let weapon = this.gameObject as HotWeapon;
// Add hot weapon callback to server
if(SystemUtil.isServer()) {
this.weapon.onEquip.add(() => {
// Logic to execute when the server's hot weapon is complete, such as updating player equipment data
console.log("onEquippedServer")
});
this.weapon.onUnequip.add(() => {
// Logic to execute when server-side hot weapon unload completes, e.g. updating player equipment data
console.log("onUnequippedServer")
});
this.weapon.fireComponent.onStartFire.add(() => {
// Logic that needs to be executed when the server-side hot weapon starts firing, such as generating a two-ended model as a bullet
console.log("onStartFireServer")
});
this.weapon.fireComponent.onEndFire.add(() => {
// logic that needs to be executed when the server-side hot weapon ends firing, such as making some weapon deformations
console.log("onEndFireServer")
});
this.weapon.fireComponent.onEndContinuousFire.add(() => {
// logic that needs to be executed at the end of a server-side hot weapon burst, such as making some weapon deformations
console.log("onEndContinuousFireServer")
});
this.weapon.reloadComponent.onStartReload.add(() => {
// Logic to execute when server-side hot weapons start reloading, e.g. updating player status
console.log("onStartReloadServer")
});
this.weapon.reloadComponent.onEndReload.add(() => {
// Logic to execute when the server-side hot weapon finishes reloading, e.g. updating player status
console.log("onEndReloadServer")
});
this.weapon.loadComponent.onStartLoad.add(() => {
// Logic to execute when server-side hot weapons start loading, e.g. updating player status
console.log("onStartLoadServer")
});
this.weapon.loadComponent.onEndLoad.add(() => {
// Logic to execute when the server hot weapon ends loading, e.g. updating the player status
console.log("onEndLoadServer")
});
this.weapon.aimComponent.onStartAim.add(() => {
// Logic to execute when the hot weapon starts aiming at the server, e.g. updating player status
console.log("onAimStartServer")
});
this.weapon.aimComponent.onEndAim.add(() => {
// Logic to execute when the server-side hot weapon ends aiming, e.g. updating the player status
console.log("onAimEndServer")
});
this.weapon.recoilForceComponent.onStartRecoil.add(() => {
// Logic to execute when the server-side hot weapon starts recoil, e.g. updating the weapon status
console.log("onStartRecoilForceServer")
});
}
// Client adds hot weapon callback
if(SystemUtil.isClient()) {
this.weapon.onEquip.add(() => {
// Logic to execute when the client's hot weapon is complete, such as playing an equipped sound effect
console.log("onEquippedClient")
});
this.weapon.onUnequip.add(() => {
// Logic that needs to be executed when the client hot weapon uninstall is complete, such as playing an equipped sound effect
console.log("onUnequippedClient")
});
this.weapon.fireComponent.onStartFire.add(() => {
// Logic to execute when the client's hot weapon starts firing, such as playing a firing sound effect
console.log("onStartFireClient")
});
this.weapon.fireComponent.onEndFire.add(() => {
// Logic that needs to be executed when the client hot weapon starts firing, e.g. update the UI interface on the number of bullets
console.log("onEndFireClient")
});
this.weapon.reloadComponent.onStartReload.add(() => {
// Logic to execute when the client hot weapon starts reloading, such as playing a reload sound effect
console.log("onStartReloadClient")
});
this.weapon.reloadComponent.onEndReload.add(() => {
// Logic that needs to be executed when the client-side hot weapon finishes reloading, e.g. update the UI interface on the number of bullets
console.log("onEndReloadClient")
});
this.weapon.loadComponent.onStartLoad.add(() => {
// Logic to execute when the client hot weapon starts loading, such as playing a loaded sound effect
console.log("onStartLoadClient")
});
this.weapon.loadComponent.onEndLoad.add(() => {
// logic that needs to be executed when the client hot weapon ends loading, such as playing an effect
console.log("onEndLoadClient")
});
this.weapon.aimComponent.onStartAim.add(() => {
// Logic to execute when the hot weapon starts aiming at the client, e.g. updating UI
console.log("onAimStartClient")
});
this.weapon.aimComponent.onEndAim.add(() => {
// Logic to execute when the client hot weapon ends aiming, e.g. updating UI
console.log("onAimEndClient")
});
this.weapon.recoilForceComponent.onStartRecoil.add(() => {
// Logic to execute when the client hot weapon starts recoil, e.g. update UI
console.log("onStartRecoilForceClient")
});
this.weapon.accuracyOfFireComponent.onCurrentDispersionChanged.add(() => {
// Logic to execute when the accuracy of the client's hot weapon fire changes, such as updating the reticle UI size.
console.log("onCurrentDispersionChangedClient")
});
}
TIP
[Fire Precision] is related to the player's camera, so events can only be triggered on the client side. When adding delegate functions, you need to be careful where you add them. In addition, client-side events trigger more slowly than receiving attribute synchronization, so you need to pay attention to latency issues when using them.