# Camera Dampers

V0.2.2 refactored the damping representation in this plugin. Before V0.2.2, all damping methods and their implementations are encapsulated in a single struct. V0.2.2 abstracts the damper representation so that each damper is relatively independent. This provides more flexibility and extensibility.&#x20;

## Using Pre-defined Dampers

Some components have already contained pre-defined dampers. For example, the ScreenFollow component contains an aggregate damper comprising three sub-dampers. Each sub-damper is responsible for damping a particular axis of current camera's positional movement.

<figure><img src="https://1253177398-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FIc7aRtmwmEkkqEJZORmC%2Fuploads%2FmUfCXlrbsoIraxhFXaJ7%2Fdamper.png?alt=media&#x26;token=466da166-2e73-4dc8-bb22-c9cfe258479b" alt=""><figcaption></figcaption></figure>

You can choose any of the pre-defined sub-damper to meet your needs. The default sub-damper is NaiveDamper. This is also the damper you're supposed to use for most of the time. It's simple and effecient, and generally lead to nice damping effects.

## Details of Pre-defined Dampers

There are six pre-defined dampers as shown below. The `Continuous Naive Damper,` `Lowpass Naive Damper`, `Restrict Naive Damper` and `Simulate Damper` are used to solve the camera jittering problem when the game's frames per second (FPS) is unstable. For most cases you should use the `Naive Damper` and for specific gameplay, you can use the `Spring Damper`.

<figure><img src="https://1253177398-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FIc7aRtmwmEkkqEJZORmC%2Fuploads%2Fcta683e6P9I069wPWXQA%2Fsub-damper.png?alt=media&#x26;token=bf107e92-3a14-4168-848c-da86e77f61ea" alt=""><figcaption></figcaption></figure>

* Naive Damper: Uses a simple residual-based damping algorithm. This is the damper you should choose for most of the time.
  * Damp Time: amount of time to finish damping.
  * Residual: damp residual after damp time (in percent).
* Simulate Damper: Splits the given deltaTime into multiple segments and simulates naive damping in order.
  * Damp Time: amount of time to finish damping.
  * Residual: damp residual after damp time (in percent).
  * Simulate Count: Number of simulations per damping.
* Continuous Naive Damper: Continuous optimization when FPS is unstable. [Reference](https://sulley.cc/2023/07/08/18/22/#solution-3-continuous-residual).
  * Damp Time: amount of time to finish damping.
  * Residual: damp residual after damp time (in percent).
  * Order: Orders of derivative you want to use for approximation. Larger means more accurate.
* Restrict Naive Damper: Restrict damp velocity when FPS in unstable. [Reference](https://sulley.cc/2023/07/08/18/22/#solution-1-imposing-an-invalid-range).
  * Damp Time: amount of time to finish damping.
  * Residual: damp residual after damp time (in percent).
  * Tolerance: Tolerance of restriction range.
  * Power: Controls how aggresively to compact the curve.
* Lowpass Naive Damper: Low-pass filtering optimization when FPS in unstable. [Reference](https://sulley.cc/2023/07/08/18/22/#solution-2-adding-low-pass-filter).
  * Damp Time: amount of time to finish damping.
  * Residual: damp residual after damp time (in percent).
  * Tolerance: Tolerance of restriction range.
  * Beta: Smaller means smoother.
* Spring Damper: Uses spring to damp. [Reference](https://sulley.cc/2024/06/18/20/06/).
  * Frequency: Controls the frequency of oscillation and the speed of decay.
  * Damp Ratio: Controls whether the spring is undamped (=0), underdamped (<1), critically damped (=1), or overdamped (>1).

## Customizing A Damper

A damper typically receives a single input value, damps it and returns the output damped value. There're six built-in dampers and you can customize your own damper.

1. Create a new blueprint class inheriting `ECameraDamper`.
2. Implement the `ApplyDamp` function and the `PostApplyDamp` function.\
   In the following figure, I create my custom damper `MyDamper`, and create two variables `DampTime` and `OtherParameters`. The `ApplyDamp` implements a simple linear damping algorithm and the `PostApplyDamp` is used to update any internal parameter.<br>

   <figure><img src="https://1253177398-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FIc7aRtmwmEkkqEJZORmC%2Fuploads%2FPHa0WQVXIuWMs5DjMQtS%2Fmydamper.png?alt=media&#x26;token=b5edb37b-1d21-41bb-9d50-aa74ce23b9d6" alt=""><figcaption></figcaption></figure>
3. Select `MyDamper` at wherever you would like to use your damper.<br>

   <figure><img src="https://1253177398-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FIc7aRtmwmEkkqEJZORmC%2Fuploads%2FEjMjXM3BinSQp7s47mcr%2Fuse.png?alt=media&#x26;token=85bae530-e47d-469d-916e-87fe78bfe7a4" alt=""><figcaption></figcaption></figure>
4. Play and see if it works correctly.<br>

   <figure><img src="https://1253177398-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FIc7aRtmwmEkkqEJZORmC%2Fuploads%2FzLOika26g4VhgPZHt0KM%2Fcorrect.png?alt=media&#x26;token=85d30cef-0350-4c8c-90ed-0017d303c59a" alt=""><figcaption></figcaption></figure>

## Customizing An Aggregate Damper

### Using Aggregate Damper for A Custom Component

An aggregate damper is a damper consisting of multiple sub-dampers, like the `ECamera Vector Damper` in ScreenFollow. It's highly related to the function and purpose of the component it resides in. For example, an `ECamera Vector Damper` aggregate damper is used for any Vector-like data, and an `ECamera Rotator Damper`, as in TargetingAim, is used for any Rotation-like data. That's to say, if you have a Vector2d data, you may prefer a `ECamera Pair Damper` aggregate damper.

To create your own `MyPairDamper` aggregate damper, create a new blueprint class inheriting `ECamera Aggregate Damper`, and create two variables of type `ECamera Damper`, designate their default damper types and parameters. That's it.

<figure><img src="https://1253177398-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FIc7aRtmwmEkkqEJZORmC%2Fuploads%2F1mJQZ6UlQTOx2cTddBh9%2Fmypairdamper.png?alt=media&#x26;token=8d81b010-065a-4de5-8f4f-26986e489ddc" alt=""><figcaption></figcaption></figure>

It should be emphasized again that your new aggregate damper **can only be used in conjunction with your own customized components**. There is no place in the built-in components where you can use your aggregate damper.

For example, in the following customized follow component `MyFollowComponent`,  I add a variable `Damper` of type `MyPairDamper`, the one we just created. Then in the Class Defaults Details panel, select `My Pair Damper`.&#x20;

<figure><img src="https://1253177398-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FIc7aRtmwmEkkqEJZORmC%2Fuploads%2FxA4hrWmhPVMAgDglNz3D%2Fdefault.png?alt=media&#x26;token=6f61acc8-936a-4026-8f19-24452f232bc5" alt=""><figcaption></figcaption></figure>

When you use this component, the default value for `Damper` will be `My Pair Damper`.

<figure><img src="https://1253177398-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FIc7aRtmwmEkkqEJZORmC%2Fuploads%2FsOz4STel7FdU07XdaUe1%2Fmyfollow.png?alt=media&#x26;token=f7c16e68-05e4-46b2-b292-e8ce3d91d7ca" alt=""><figcaption></figcaption></figure>

So how do you update this custom damper inside your component? Two steps.

The first step is to define several update functions in your damper. In the example of `MyPairDamper`, you can define four functions:

* SetInput：Take a Vector2D data as input and feed the X/Y component to Damper X/Y. The input will be damped by a damper.
* SetOutput: Take a Vector2D data as input and feed the X/Y component to Damper X/Y. This is an interface to allow external modifications on the output derived by a damper. The modified output is then propagated into the damper internally.
* ApplyDamp: Each damper applies damping.
* PostApplyDamp: An interface allowing each damper to update its internal parameters. For example, the `Spring Damper` has velocity as its internal mutable parameter and is updated each frame.

<figure><img src="https://1253177398-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FIc7aRtmwmEkkqEJZORmC%2Fuploads%2Fy4U8lv0RUYXpECAdko5l%2Ffunction.png?alt=media&#x26;token=120f0e4c-642b-446e-9621-706ed351da94" alt=""><figcaption></figcaption></figure>

A typical workflow of an aggregate damper is to sequentially call SetInput->ApplyDamp->SetOutput (Optional)->PostApplyDamp.

In the following example of `MyFollowComponent`, you can see how the `Damper` processes the `Position` variable.

<figure><img src="https://1253177398-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FIc7aRtmwmEkkqEJZORmC%2Fuploads%2FOO1KGviYl6mah4IvDrmS%2Fworkflow.png?alt=media&#x26;token=995a4594-9792-48cd-a7e0-1f8df1135b0b" alt=""><figcaption></figcaption></figure>

### Using Aggregate Damper As Template

You can also comprehen an aggregate damper as a template. For example, in some cases you may want all the three sub-dampers in `ECamera Damper Vector` to be `Spring Damper`, and in other cases, you want the `Damper X` to be `Spring Damper` and `Damper Y/Z` to be `Naive Damper`. To this end, you can inherit `ECamera Damper Vector` and specify the concrete type for each sub-damper. Then, in the component, say ScreenFollow, you can directly use your customized version of `ECamera Damper Vector`  without specifying the type of each sub-damper.

As an example, I create my own aggregate damper named `MyDamperVector` inheriting from `ECamera Damper Vector`  and have all sub-dampers be `Spring Damper`.

<figure><img src="https://1253177398-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FIc7aRtmwmEkkqEJZORmC%2Fuploads%2FACrZ5KsMymwIOolffDXS%2Fdampervector.png?alt=media&#x26;token=869fc02d-da4a-4fdc-9bab-1db105b45c3b" alt=""><figcaption></figcaption></figure>

In the ScreenFollow component, all I need to do is choose `My Damper Vector`. This will save much time tuning the types and parameters of sub-dampers for each component of each camera by customizing some commonly-used damper templates.

<figure><img src="https://1253177398-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FIc7aRtmwmEkkqEJZORmC%2Fuploads%2FnM63P9pwIcCsSxT2zSF2%2Fdampervector_1.png?alt=media&#x26;token=be2712d9-69d4-4740-a5d6-821dc026493d" alt=""><figcaption></figcaption></figure>
