top of page

Zenless Zone Zero Combat Demo

Made by Unreal 5

This is a combat demo of Zenless Zone Zero recreated in Unreal Engine 5. It faithfully replicates the original game's combat system while emphasizing a programmatic design approach. The framework offers efficient, easy-to-understand interfaces for Blueprints, enabling rapid character integration once the system is stable. A simple enemy AI has also been developed for testing purposes. Extensive configuration files are included to easily modify character data and other parameters.

​(All characters and animations used in this demo are the property of miHoYo. This project is purely for non-commercial purposes.)

Demo Video

Weixin Image_20250502124702.png

In this demo, multiple systems were developed in C++ to faithfully recreate the combat system of Zenless Zone Zero. The framework is designed with a strong emphasis on collaboration between engineers and designers, with careful consideration given to providing sufficient interfaces for designers to quickly configure new characters. The implemented systems include a custom state machine tailored to the project, a combat system component, an input cache system, and more. Since the original character skeletons were not compatible with Root Motion in Unreal Engine, a custom UE plugin was also developed to modify skeletal data accordingly. The following sections introduce several core systems to demonstrate the overall design logic and implementation methods.

​

StateMachine

First, the game's animations were divided into two parts. One part is Locomotion, which includes animations like Idle, Walk, and Run that are driven by directional input. This portion is handled using an Animation Blueprint, where character states are switched by updating variables that automatically trigger animation transitions. The second part involves combat-related animations, such as various attacks, dodges, and parries. These animations are implemented as Animation Montages, which are played when the character enters the corresponding state. Within each state, different inputs can trigger transitions to other states. The conditions for transitioning out of a state, and which states are allowed as targets, are all defined within each individual state.

Weixin Image_20250503091803.png
All States used on Anby

In C++, foundational logic for common states such as Attack, Dash, Idle, and Run is implemented, with behavior interfaces exposed to Blueprints. This allows designers to quickly define the specific behavior of each state in Blueprint, enabling efficient collaboration between engineers and gameplay/system designers.

State Blueprint Setup

Combat System Component

Analyzing the original Zenless Zone Zero combat system reveals that its damage calculation is quite complex. Damage can be influenced by a variety of factors, such as the character's critical rate, critical damage, penetration rate, self buffs, enemy buffs, and the enemy’s defense. Additionally, when a monster takes damage, it accumulates an anomaly value based on the type of damage and the character’s attributes. Once this value reaches a certain threshold, a corresponding anomaly effect is triggered. Furthermore, overlapping anomaly effects can lead to a special effect known as "Disorder," which serves as an anomaly resolution mechanic.

​

Given this complexity, a robust, extensible system for receiving and processing damage is especially important—this is the reason for introducing a dedicated component.

In the current implementation of the Zenless Zone Zero combat system, monsters do not apply abnormality effects to Agents. In other words, the damage processing logic differs between agents and enemies. Therefore, after establishing a base combat system component class, two separate components were created: AgentCombatSystem for agents and EnemyCombatSystem for enemies, each handling damage logic appropriate to their roles.

Input Cache System

In action games, frame feedback is extremely sensitive. For example, when the player presses the attack button, the character should perform Attack Action 1. During this action, if the animation reaches the frame range between 80 and 120 and the player inputs another attack command, Attack Action 2 should be triggered.

​

In this scenario, if the player continuously taps the attack button during the execution of Attack Action 1, ideally, Attack Action 2 should be triggered precisely when the animation reaches frame 80. However, in practice, even with rapid button spamming, it's difficult for the player to hit the exact frame needed to trigger the next action.

​

To ensure that the trigger timing for Action 2 remains consistent regardless of slight input timing differences, an Input Cache System is used.

Before the trigger window for Action 2, a short-duration NotifyState is inserted into the animation timeline. When this NotifyState begins, the Input Cache System is activated to start recording the player's inputs. Then, when the trigger point for Action 2 is reached (ANS_AttackChain), the system checks the cache for a valid input. If a valid input is found, the corresponding action is executed immediately.

​

This ensures that every time the trigger point is reached, the system responds consistently to the player's current input behavior, providing a smoother and more reliable combat experience.

Configurations

Anby configuration

Enemy configuration

The configuration files should be easy to modify, logically organized, and convenient to manage. The examples provided include configuration files for the character Anby and a test Enemy, covering nearly all parameters used in Zenless Zone Zero.

​

In the actual presentation of Zenless Zone Zero, all attack damage needs to be visually represented to the player. However, the game's damage system cannot always be designed with a single, unified format. For a given attack—or a single animation—damage may be applied in segments. Therefore, each segment of an attack should have its own separate data and corresponding visual representation.

Plugin for modifying animations

In the original animations, the Bip001 bone contains the Root Motion data, which makes it incompatible with Root Motion usage in Unreal Engine. To resolve this, I need to remove the Root Motion data (position and rotation) from Bip001, and then transfer that data to Avatar_Female_Size02_Anbi, which is the actual Root node. So I wrote a plugin to handle this process.

As you can see, after the modification, the Bip001 bone no longer contains any Root Motion data. Once the original Root Motion data is assigned to the actual Root bone, the animation can be used as a proper Root Motion animation.

bottom of page