как сделать что бы проигрывались в анимации враг и...
创建于:2025年5月8日
创建于:2025年5月8日
как сделать что бы проигрывались в анимации враг и игрок, и что бы пока хитбокс не находит игрока, анимация не проигрывалась
Ниже — «канонический» способ решить задачу для самых популярных движков. Если вы пользуетесь Unity, читайте первый блок; если Godot — второй. Если у вас другой стек, дайте знать — подскажу подробнее.
Структура анимаций
В Animator добавьте bool-параметр playerInRange
.
Переходы
playerInRange == true
playerInRange == false
Хитбоксы
SphereCollider
или BoxCollider
с галкой Is Trigger и задаём слой, с которым он должен пересекаться (обычно Player
).csharppublic class EnemyAI : MonoBehaviour { public Animator anim; void OnTriggerEnter (Collider other) { if (other.CompareTag("Player")) anim.SetBool("playerInRange", true); } void OnTriggerExit (Collider other) { if (other.CompareTag("Player")) anim.SetBool("playerInRange", false); } }
До тех пор, пока playerInRange
ложно, состояние Attack никогда не активируется — анимация «спит».
Оптимизация
Если врагов много, рассматривайте Animator Culling, чтобы движение вне камеры не тратило кадры.
Сцена
KinematicBody2D
(CharacterBody2D
в Godot 4)AnimationPlayer
+ AnimationTree
Area2D
(«агро-хитбокс») с CollisionShape2D
AnimationTree
BlendSpace1D
или StateMachine
.walk
, attack
.player_in_range
(или добавьте AnimationNodeOneShot
и задавайте active
).Сигналы от Area2D
gdscriptextends CharacterBody2D @onready var anim_tree = $AnimationTree @onready var area = $Area2D func _ready(): area.body_entered.connect(_on_body_entered) area.body_exited.connect(_on_body_exited) func _on_body_entered(body): if body.is_in_group("player"): anim_tree.set("parameters/player_in_range", true) func _on_body_exited(body): if body.is_in_group("player"): anim_tree.set("parameters/player_in_range", false)
Пока игрока нет в Area2D
, значение player_in_range
— false
, и узел AnimationTree
продолжит отдавать само Idle/Walk.
Attack
-анимации (например, через AnimationEvent
/Call Method Track
).yield(get_tree().create_timer(0.1), "timeout")
) перед установкой флага или в Animator добавьте Transition Exit Time
.Спрашивайте, если нужно больше примеров или другой движок — помогу!
сделай на платформе Roblox studio
Ниже пример для NPC-врага. Для игрока принцип такой же: своя зона детекции → переключаем Attack/Idle.
rbxassetid://1234567890
).textEnemy (Model) ├─ HumanoidRootPart ├─ Humanoid ├─ … (тело) └─ Detector (Part) ← «агро-зона»
Transparency = 1
)CanCollide = false
, Anchored = true
HumanoidRootPart
.Поместите Script (НЕ LocalScript) в модель врага.
lualocal npc = script.Parent local humanoid = npc:WaitForChild("Humanoid") local detector = npc:WaitForChild("Detector") -- Part -- === загружаем анимации === local idleAnim = Instance.new("Animation") idleAnim.AnimationId = "rbxassetid://ID_IDLE" -- замените! local attackAnim = Instance.new("Animation") attackAnim.AnimationId = "rbxassetid://ID_ATTACK" -- замените! local idleTrack = humanoid:LoadAnimation(idleAnim) local attackTrack = humanoid:LoadAnimation(attackAnim) idleTrack.Looped = true -- крутится постоянно attackTrack.Looped = true -- можно false, если анимация короткая idleTrack:Play() -- стартуем в покое -- === вспомогательные функции === local function switchToAttack() if attackTrack.IsPlaying then return end idleTrack:Stop() attackTrack:Play() end local function switchToIdle() if idleTrack.IsPlaying then return end attackTrack:Stop() idleTrack:Play() end -- === обработка входа / выхода игрока === local players = game:GetService("Players") local function isPlayer(part) local char = part.Parent return players:GetPlayerFromCharacter(char) ~= nil end detector.Touched:Connect(function(part) if isPlayer(part) then switchToAttack() end end) -- TouchEnded работает не всегда надёжно, лучше раз 0.1 с проверять, -- есть ли игроки в зоне: while true do task.wait(0.1) local stillHasPlayer = false for _,p in ipairs(detector:GetTouchingParts()) do if isPlayer(p) then stillHasPlayer = true break end end if stillHasPlayer then switchToAttack() else switchToIdle() end end
Player
-персонаж заходит в Detector
, скрипт останавливает Idle и запускает Attack.TouchEnded
, которое не срабатывает, когда объект удалён/телепортирован.)Тема | Совет |
---|---|
Клиент ↔ сервер | Анимации, запущенные с Script на сервере, автоматически реплицируются всем клиентам. |
Оптимизация | Если в игре много врагов, останавливайте Idle совсем (idleTrack:AdjustSpeed(0) ) для NPC за пределами видимости или отключайте Detector при удалении от игрока. |
Ударный хитбокс | Для нанесения урона лучше завести второй Part поменьше, привязанный к руке/оружию. Активируйте его только внутри Attack-анимации (через AnimationTrack:GetMarkerReachedSignal("SwingStart") ). |
Игрок | У игрока делайте то же самое, но, как правило, логику детекции пишут в Tool или LocalScript (чтобы реакция была без задержек). |
Попробуйте добавить скрипт и убедиться, что NPC переключает анимации при подходе. Если нужна помощь с маркерами, дистанционными атаками или оптимизацией для больших карт — дайте знать!