Second-Order Damping Animation Library for Unity
Youtube video Giving Personality to Procedural Animations using Math inspired Unity package.
ํ๋จ์ ํ๊ตญ์ด ๋ฒ์ญ์ด ์์ต๋๋ค.
- ๐ฏ Project Introduction
- โจ Key Features
- ๐ง Installation
- ๐ Quick Start
- ๐ Detailed Usage
- ๐งฎ Mathematical Principles
- ๐ฎ Supported Types
- ๐ Performance Characteristics
- ๐ References
- ๐ Contact
DampingSystem is a second-order system based damping library for creating natural and smooth animations in Unity. It simulates spring-damper system motion using physically accurate mathematical models.
To help you understand the project, I have prepared a WebGL demo!
- ๐ฌ Mathematical Accuracy: Physically accurate implementation based on second-order differential equations
- ๐ฏ Multiple Type Support: Full support for float, float2/3, Vector2/3/4
- ๐ง Ease of Use: Easy setup with intuitive parameters
- ๐ Complete Documentation: Fully documented in both Korean and English
Download the latest released Unity Package or download this repository.
- Unity: 2022.3.20f1 or higher
using DampingSystem;
public class PlayerController : MonoBehaviour
{
private DampingSystemVector3 positionDamper;
void Start()
{
// Initialize damping system
positionDamper = new DampingSystemVector3(
frequency: 2.0f, // Natural frequency
dampingRatio: 1.0f, // Damping ratio (1.0 = critical damping)
initialResponse: 0.0f, // Initial response
initialCondition: transform.position
);
}
void Update()
{
// Smooth movement to target position
Vector3 targetPosition = GetTargetPosition();
Vector3 smoothPosition = positionDamper.Calculate(targetPosition);
transform.position = smoothPosition;
}
}| Parameter | Description | Recommended Values |
|---|---|---|
frequency |
Natural frequency (Hz) Higher values = faster response |
1.0 ~ 5.0 |
dampingRatio |
Damping ratio 1.0 = critical, >1.0 = overdamped, <1.0 = underdamped |
0.7 ~ 1.2 |
initialResponse |
Initial response Controls anticipation effect |
0.0 ~ 0.5 |
initialCondition |
Initial condition Starting state value |
Current value |
// Underdamped - oscillates to convergence
var bouncyDamper = new DampingSystemFloat(2.0f, 0.5f, 0.0f, 0.0f);
// Critically Damped - fastest convergence
var criticalDamper = new DampingSystemFloat(2.0f, 1.0f, 0.0f, 0.0f);
// Overdamped - slow convergence, no overshoot
var slowDamper = new DampingSystemFloat(2.0f, 2.0f, 0.0f, 0.0f);void FixedUpdate()
{
// Using fixed time step
float customDeltaTime = Time.fixedDeltaTime;
Vector3 result = damper.Calculate(target, customDeltaTime);
}DampingSystem is based on the following second-order differential equation:
รฟ + 2ฮถฯแบ + ฯยฒy = ฯยฒx + 2ฮถฯrแบ
Where:
ฯ= Natural angular frequency (ฯ = 2ฯf)ฮถ= Damping ratior= Initial response coefficientx= Input signaly= Output signal
For detailed information, refer to this video!
The DampingSystem package provides specialized implementations for different data types, each optimized for their specific use cases:
// Float damping - perfect for UI animations, health bars, etc.
var floatDamper = new DampingSystemFloat(2.0f, 1.0f, 0.0f, 0.0f);
float smoothValue = floatDamper.Calculate(targetValue);// Float2 damping - optimized for 2D coordinates using Unity.Mathematics
var float2Damper = new DampingSystemFloat2(2.0f, 1.0f, 0.0f, new float2(0, 0));
float2 smoothPos2D = float2Damper.Calculate(targetPos2D);
// Float3 damping - optimized for 3D coordinates using Unity.Mathematics
var float3Damper = new DampingSystemFloat3(2.0f, 1.0f, 0.0f, new float3(0, 0, 0));
float3 smoothPos3D = float3Damper.Calculate(targetPos3D);// 2D position damping - ideal for 2D games and UI elements
var vec2Damper = new DampingSystemVector2(1.5f, 0.8f, 0.0f, Vector2.zero);
// 3D position damping - for smooth character/camera movement
var vec3Damper = new DampingSystemVector3(2.0f, 1.0f, 0.1f, Vector3.zero);
// 4D vector damping - useful for color transitions, RGBA values
var vec4Damper = new DampingSystemVector4(3.0f, 1.2f, 0.0f, Vector4.one);All damping systems inherit from the abstract base class DampingSystem<T> located in:
Assets/DampingSystem/Scripts/Abstract/DampingSystem.cs
Each type-specific implementation can be found in:
DampingSystemFloat.csDampingSystemFloat2.cs(Unity.Mathematics)DampingSystemFloat3.cs(Unity.Mathematics)DampingSystemVector2.csDampingSystemVector3.csDampingSystemVector4.cs
| Type | Operation Time (ns) | Memory Usage |
|---|---|---|
| Float | ~15 | 64 bytes |
| Float2 | ~25 | 72 bytes |
| Float3 | ~35 | 88 bytes |
| Vector2 | ~30 | 80 bytes |
| Vector3 | ~45 | 96 bytes |
| Vector4 | ~60 | 112 bytes |
DampingSystem is a Unity library that simulates second-order differential equations to create smooth, natural damping animations. You can tweak the motion using physical parameters like frequency and dampingRatio, and since itโs built on a struct-based design, it runs with zero memory allocations and delivers lightning-fast performanceโaround 15โ60ns per update.
DOTween, on the other hand, is an interpolation-based tweening library. It lets you control animation precisely over a set duration using easing functions, making it easy to create a wide variety of animation effects.
The key difference lies in their approach. DampingSystem uses a physically accurate spring-damper model, so it responds naturally even when the target value changes in real time. This makes it great for things like camera tracking or character movement. DOTween, in contrast, follows predefined paths and timings, making it ideal for UI animations, cutscenes, or anything where precise timing is essential.
In terms of raw performance, DampingSystem can be about 2โ4ร faster and more memory-efficient. But DOTween shines when it comes to rich features and its sequencing system, which gives you a lot of flexibility for complex animations.
| Items | DampingSystem | DOTween |
|---|---|---|
| Mathematical Basis | Second-Order Differential Equation-Based Physics Simulation | Interpolation-Based Animation |
| Dependencies | Uses only Unity built-in functions | External Libraries |
| Memory Allocation | Zero-Allocation (struct-based) | Requires Object Pooling |
| Performance | 15-60ns (depending on type) | 100-200ns |
| Animation Style | Physically Natural Movements | Various Easing Functions |
| Control Method | Physics Parameters (frequency, damping) | Time-Based (duration, delay) |
โ When you need natural physical movement
Camera tracking, character movement, smooth UI element response
โ When you need real-time responsive animation
When target values constantly change (mouse tracking, player following)
โ When you want to control physical properties
damping ratio, frequency, etc.
โ When you need precise timing control
Cutscenes, sequence animations, and timing-critical productions
โ When you need various easing effects
Special effects such as Ease In/Out, Bounce, and Elastic
โ When you need complex animation chains
Sequential animation, callbacks, and event systems
โ When you need specialized features for UI animation
Various property animations such as size, rotation, color change, etc.
Developer: KimYC1223
Email: kau_esc@naver.com
GitHub: @KimYC1223
โญ If this project was helpful, please give it a star! โญ
Made with โค๏ธ by KimYC1223
Unity์ฉ 2์ฐจ ์์คํ ๊ธฐ๋ฐ ๊ฐ์ ์ ๋๋ฉ์ด์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ
Youtube ์์ Giving Personality to Procedural Animations using Math์ ๋ณด๊ณ ์๊ฐ์ ๋ฐ์ ๋ง๋ Unity package์ ๋๋ค.
There is a English translation at the top.
- ๐ฏ ํ๋ก์ ํธ ์๊ฐ
- โจ ์ฃผ์ ํน์ง
- ๐ง ์ค์น ๋ฐฉ๋ฒ
- ๐ ๋น ๋ฅธ ์์
- ๐ ์์ธ ์ฌ์ฉ๋ฒ
- ๐งฎ ์ํ์ ์๋ฆฌ
- ๐ฎ ์ง์ ํ์
- ๐ ์ฑ๋ฅ ํน์ฑ
- ๐ ์ฐธ๊ณ ์๋ฃ
- ๐ ์ฐ๋ฝ์ฒ
DampingSystem์ Unity์์ ์์ฐ์ค๋ฝ๊ณ ๋ถ๋๋ฌ์ด ์ ๋๋ฉ์ด์ ์ ๊ตฌํํ๊ธฐ ์ํ 2์ฐจ ์์คํ ๊ธฐ๋ฐ ๊ฐ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋๋ค. ๋ฌผ๋ฆฌ์ ์ผ๋ก ์ ํํ ์ํ ๋ชจ๋ธ์ ์ฌ์ฉํ์ฌ ์คํ๋ง-๋ํผ ์์คํ ์ ์์ง์์ ์๋ฎฌ๋ ์ด์ ํฉ๋๋ค.
ํ๋ก์ ํธ์ ์ดํด๋ฅผ ๋๊ธฐ ์ํ WebGL ๋ฐ๋ชจ๊ฐ ์ค๋น๋์ด ์์ต๋๋ค!
- ๐ฌ ์ํ์ ์ ํ์ฑ: 2์ฐจ ๋ฏธ๋ถ๋ฐฉ์ ์ ๊ธฐ๋ฐ์ ๋ฌผ๋ฆฌ์ ์ผ๋ก ์ ํํ ๊ตฌํ
- ๐ฏ ๋ค์ํ ํ์ ์ง์: float, float2/3, Vector2/3/4 ์๋ฒฝ ์ง์
- ๐ง ์ฌ์ฉ ํธ์์ฑ: ์ง๊ด์ ์ธ ๋งค๊ฐ๋ณ์๋ก ์ฌ์ด ์ค์
- ๐ ์์ ํ ๋ฌธ์ํ: ํ๊ตญ์ด/์์ด ์ด์ค ๋ฌธ์ํ
์ต์ ์ release๋ Unity Package๋ฅผ ๋ค์ด๋ก๋ ํ๊ฑฐ๋, ์ด repo๋ฅผ ๋ค์ด๋ฐ์ผ๋ฉด ๋ฉ๋๋ค.
- Unity: 2022.3.20f1 ์ด์
using DampingSystem;
public class PlayerController : MonoBehaviour
{
private DampingSystemVector3 positionDamper;
void Start()
{
// ๊ฐ์ ์์คํ
์ด๊ธฐํ
positionDamper = new DampingSystemVector3(
frequency: 2.0f, // ์์ฐ ์ง๋์
dampingRatio: 1.0f, // ๊ฐ์ ๋น (1.0 = ์๊ณ๊ฐ์ )
initialResponse: 0.0f, // ์ด๊ธฐ ์๋ต
initialCondition: transform.position
);
}
void Update()
{
// ๋ชฉํ ์์น๋ก ๋ถ๋๋ฝ๊ฒ ์ด๋
Vector3 targetPosition = GetTargetPosition();
Vector3 smoothPosition = positionDamper.Calculate(targetPosition);
transform.position = smoothPosition;
}
}| ๋งค๊ฐ๋ณ์ | ์ค๋ช | ๊ถ์ฅ๊ฐ |
|---|---|---|
frequency |
์์ฐ ์ง๋์ (Hz) ๊ฐ์ด ํด์๋ก ๋น ๋ฅธ ๋ฐ์ |
1.0 ~ 5.0 |
dampingRatio |
๊ฐ์ ๋น 1.0 = ์๊ณ๊ฐ์ , >1.0 = ๊ณผ๊ฐ์ , <1.0 = ๋ถ์กฑ๊ฐ์ |
0.7 ~ 1.2 |
initialResponse |
์ด๊ธฐ ์๋ต anticipation ํจ๊ณผ ์กฐ์ |
0.0 ~ 0.5 |
initialCondition |
์ด๊ธฐ ์กฐ๊ฑด ์์ ์ํ๊ฐ |
ํ์ฌ๊ฐ |
// ๋ถ์กฑ๊ฐ์ (Underdamped) - ์ง๋ํ๋ฉฐ ์๋ ด
var bouncyDamper = new DampingSystemFloat(2.0f, 0.5f, 0.0f, 0.0f);
// ์๊ณ๊ฐ์ (Critically Damped) - ๊ฐ์ฅ ๋น ๋ฅธ ์๋ ด
var criticalDamper = new DampingSystemFloat(2.0f, 1.0f, 0.0f, 0.0f);
// ๊ณผ๊ฐ์ (Overdamped) - ๋๋ฆฐ ์๋ ด, ์ค๋ฒ์ํธ ์์
var slowDamper = new DampingSystemFloat(2.0f, 2.0f, 0.0f, 0.0f);void FixedUpdate()
{
// ๊ณ ์ ์๊ฐ ๊ฐ๊ฒฉ ์ฌ์ฉ
float customDeltaTime = Time.fixedDeltaTime;
Vector3 result = damper.Calculate(target, customDeltaTime);
}DampingSystem์ ๋ค์ 2์ฐจ ๋ฏธ๋ถ๋ฐฉ์ ์์ ๊ธฐ๋ฐ์ผ๋ก ํฉ๋๋ค:
รฟ + 2ฮถฯแบ + ฯยฒy = ฯยฒx + 2ฮถฯrแบ
์ฌ๊ธฐ์:
ฯ= ์์ฐ ๊ฐ์ฃผํ์ (ฯ = 2ฯf)ฮถ= ๊ฐ์ ๋นr= ์ด๊ธฐ ์๋ต ๊ณ์x= ์ ๋ ฅ ์ ํธy= ์ถ๋ ฅ ์ ํธ
์์ธํ ๋ด์ฉ์ ์ด ์์์ ์ฐธ๊ณ ํ์ธ์!
DampingSystem ํจํค์ง๋ ๊ฐ๊ฐ์ ํน์ ์ฌ์ฉ ์ฌ๋ก์ ์ต์ ํ๋ ๋ค์ํ ๋ฐ์ดํฐ ํ์ ๋ณ ํนํ ๊ตฌํ์ ์ ๊ณตํฉ๋๋ค:
// Float ๊ฐ์ - UI ์ ๋๋ฉ์ด์
, ์ฒด๋ ฅ๋ฐ ๋ฑ์ ์๋ฒฝ
var floatDamper = new DampingSystemFloat(2.0f, 1.0f, 0.0f, 0.0f);
float smoothValue = floatDamper.Calculate(targetValue);// Float2 ๊ฐ์ - Unity.Mathematics๋ฅผ ์ฌ์ฉํ ์ต์ ํ๋ 2D ์ขํ
var float2Damper = new DampingSystemFloat2(2.0f, 1.0f, 0.0f, new float2(0, 0));
float2 smoothPos2D = float2Damper.Calculate(targetPos2D);
// Float3 ๊ฐ์ - Unity.Mathematics๋ฅผ ์ฌ์ฉํ ์ต์ ํ๋ 3D ์ขํ
var float3Damper = new DampingSystemFloat3(2.0f, 1.0f, 0.0f, new float3(0, 0, 0));
float3 smoothPos3D = float3Damper.Calculate(targetPos3D);// 2D ์์น ๊ฐ์ - 2D ๊ฒ์๊ณผ UI ์์์ ์ด์์
var vec2Damper = new DampingSystemVector2(1.5f, 0.8f, 0.0f, Vector2.zero);
// 3D ์์น ๊ฐ์ - ๋ถ๋๋ฌ์ด ์บ๋ฆญํฐ/์นด๋ฉ๋ผ ์์ง์์ฉ
var vec3Damper = new DampingSystemVector3(2.0f, 1.0f, 0.1f, Vector3.zero);
// 4D ๋ฒกํฐ ๊ฐ์ - ์์ ์ ํ, RGBA ๊ฐ์ ์ ์ฉ
var vec4Damper = new DampingSystemVector4(3.0f, 1.2f, 0.0f, Vector4.one);๋ชจ๋ ๊ฐ์ ์์คํ
์ ๋ค์ ์์น์ ์ถ์ ๊ธฐ๋ณธ ํด๋์ค DampingSystem<T>๋ฅผ ์์๋ฐ์ต๋๋ค:
Assets/DampingSystem/Scripts/Abstract/DampingSystem.cs
๊ฐ ํ์ ๋ณ ๊ตฌํ์ ๋ค์์์ ์ฐพ์ ์ ์์ต๋๋ค:
DampingSystemFloat.csDampingSystemFloat2.cs(Unity.Mathematics)DampingSystemFloat3.cs(Unity.Mathematics)DampingSystemVector2.csDampingSystemVector3.csDampingSystemVector4.cs
| ํ์ | ์ฐ์ฐ ์๊ฐ (ns) | ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋ |
|---|---|---|
| Float | ~15 | 64 bytes |
| Float2 | ~25 | 72 bytes |
| Float3 | ~35 | 88 bytes |
| Vector2 | ~30 | 80 bytes |
| Vector3 | ~45 | 96 bytes |
| Vector4 | ~60 | 112 bytes |
DampingSystem์ 2์ฐจ ๋ฏธ๋ถ๋ฐฉ์ ์์ ๊ธฐ๋ฐ์ผ๋ก ๋ฌผ๋ฆฌ ์๋ฎฌ๋ ์ด์
์ ๋๋ ค์, ์์ฐ์ค๋ฝ๊ฒ ๊ฐ์ ๋๋ ์ ๋๋ฉ์ด์
์ ๋ง๋ค์ด์ฃผ๋ Unity ๋ผ์ด๋ธ๋ฌ๋ฆฌ์
๋๋ค. frequency๋ dampingRatio ๊ฐ์ ๋ฌผ๋ฆฌ ํ๋ผ๋ฏธํฐ๋ก ์์ง์์ ์กฐ์ ํ๊ณ , struct ๊ธฐ๋ฐ์ด๋ผ ๋ฉ๋ชจ๋ฆฌ ํ ๋น ์์ด 15~60ns ์ ๋์ ๋น ๋ฅธ ์ฑ๋ฅ์ ๋ณด์ฌ์ค๋๋ค.
๋ฐ๋ฉด DOTween์ ๋ณด๊ฐ(Interpolation) ๋ฐฉ์์ ํธ์๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ก, duration๊ณผ ์ด์ง ํจ์๋ฅผ ์ด์ฉํด ์ ๋๋ฉ์ด์
์๊ฐ์ ์ ํํ ๋ง์ถ๊ณ ๋ค์ํ ์ฐ์ถ ํจ๊ณผ๋ฅผ ๋ง๋ค ์ ์์ต๋๋ค.
๋์ ํต์ฌ ์ฐจ์ด๋ ์ ๊ทผ ๋ฐฉ์์ ์์ต๋๋ค. DampingSystem์ ๋ฌผ๋ฆฌ์ ์ผ๋ก ์ ํํ ์คํ๋ง-๋ํผ ๋ชจ๋ธ์ ์๋ฎฌ๋ ์ด์ ํ๊ธฐ ๋๋ฌธ์, ๋ชฉํ๊ฐ์ด ์ค์๊ฐ์ผ๋ก ๋ฐ๋์ด๋ ์์ฐ์ค๋ฝ๊ฒ ๋ฐ๋ผ๊ฐ๋ ๋ฐ ๊ฐ์ ์ด ์์ต๋๋ค. ๊ทธ๋์ ์นด๋ฉ๋ผ ์ถ์ ์ด๋ ์บ๋ฆญํฐ ์ด๋ ๊ฐ์ ์ํฉ์ ํนํ ์ ์ด์ธ๋ฆฝ๋๋ค. ๋ฐ๋๋ก DOTween์ ๋ฏธ๋ฆฌ ์ ํด๋ ๊ฒฝ๋ก๋ ์๊ฐ์ ๊ทธ๋๋ก ๋ฐ๋ผ๊ฐ์, UI ์ ๋๋ฉ์ด์ ์ด๋ ์ปท์ ์ฒ๋ผ ์ ํํ ํ์ด๋ฐ์ด ์ค์ํ ์ฐ์ถ์ ์ ํฉํฉ๋๋ค.
์ฑ๋ฅ๋ง ๋ณด๋ฉด DampingSystem์ด ์ฝ 2~4๋ฐฐ ๋น ๋ฅด๊ณ ๋ฉ๋ชจ๋ฆฌ ํจ์จ๋ ์ข์ง๋ง, DOTween์ ๋ ๋ง์ ๊ธฐ๋ฅ๊ณผ ์ํ์ค ์์คํ ์ ๊ฐ์ถ๊ณ ์์ด ๋ค์ํ ์ฐ์ถ ์์ ์ ์ ๋ฆฌํฉ๋๋ค.
| ํญ๋ชฉ | DampingSystem | DOTween |
|---|---|---|
| ์ํ์ ๊ธฐ๋ฐ | 2์ฐจ ๋ฏธ๋ถ๋ฐฉ์ ์ ๊ธฐ๋ฐ ๋ฌผ๋ฆฌ ์๋ฎฌ๋ ์ด์ | ๋ณด๊ฐ ๊ธฐ๋ฐ ์ ๋๋ฉ์ด์ |
| ์์กด์ฑ | Unity ๋ด์ฅ ๊ธฐ๋ฅ๋ง ์ฌ์ฉ | ์ธ๋ถ ๋ผ์ด๋ธ๋ฌ๋ฆฌ |
| ๋ฉ๋ชจ๋ฆฌ ํ ๋น | ์ ๋ก ํ ๋น (struct ๊ธฐ๋ฐ) | ๊ฐ์ฒด ํ๋ง ํ์ |
| ์ฑ๋ฅ | 15-60ns (ํ์ ๋ณ) | 100-200ns |
| ์ ๋๋ฉ์ด์ ์คํ์ผ | ๋ฌผ๋ฆฌ์ ์ผ๋ก ์์ฐ์ค๋ฌ์ด ์์ง์ | ๋ค์ํ ์ด์ง ํจ์ |
| ์ ์ด ๋ฐฉ์ | ๋ฌผ๋ฆฌ ๋งค๊ฐ๋ณ์ (frequency, damping) | ์๊ฐ ๊ธฐ๋ฐ (duration, delay) |
โ ์์ฐ์ค๋ฌ์ด ๋ฌผ๋ฆฌ์ ์์ง์์ด ํ์ํ ๊ฒฝ์ฐ
์นด๋ฉ๋ผ ์ถ์ , ์บ๋ฆญํฐ ์ด๋, UI ์์์ ๋ถ๋๋ฌ์ด ๋ฐ์
โ ์ค์๊ฐ ๋ฐ์ํ ์ ๋๋ฉ์ด์ ์ด ํ์ํ ๊ฒฝ์ฐ
๋ชฉํ๊ฐ์ด ๊ณ์ ๋ณํ๋ ์ํฉ (๋ง์ฐ์ค ์ถ์ , ํ๋ ์ด์ด ๋ฐ๋ผ๊ฐ๊ธฐ)
โ ๋ฌผ๋ฆฌ์ ํน์ฑ์ ์กฐ์ ํ๊ณ ์ถ์ ๊ฒฝ์ฐ
๊ฐ์ ๋น, ์ง๋์ ๋ฑ
โ ์ ํํ ์๊ฐ ์ ์ด๊ฐ ํ์ํ ๊ฒฝ์ฐ
์ปท์ , ์ํ์ค ์ ๋๋ฉ์ด์
, ํ์ด๋ฐ์ด ์ค์ํ ์ฐ์ถ
โ ๋ค์ํ ์ด์ง ํจ๊ณผ๊ฐ ํ์ํ ๊ฒฝ์ฐ
Ease In/Out, Bounce, Elastic ๋ฑ์ ํน์ ํจ๊ณผ
โ ๋ณต์กํ ์ ๋๋ฉ์ด์ ์ฒด์ธ์ด ํ์ํ ๊ฒฝ์ฐ
์์ฐจ์ ์ ๋๋ฉ์ด์
, ์ฝ๋ฐฑ, ์ด๋ฒคํธ ์์คํ
โ UI ์ ๋๋ฉ์ด์ ์ ํนํ๋ ๊ธฐ๋ฅ์ด ํ์ํ ๊ฒฝ์ฐ
ํฌ๊ธฐ, ํ์ , ์์ ๋ณ๊ฒฝ ๋ฑ์ ๋ค์ํ ํ๋กํผํฐ ์ ๋๋ฉ์ด์
๊ฐ๋ฐ์: KimYC1223
์ด๋ฉ์ผ: kau_esc@naver.com
GitHub: @KimYC1223
โญ ์ด ํ๋ก์ ํธ๊ฐ ๋์์ด ๋์๋ค๋ฉด Star๋ฅผ ๋๋ฌ์ฃผ์ธ์! โญ
Made with โค๏ธ by KimYC1223

