public void UseDash(DashData dashData)
{
var dashDirection = dashData.Type switch
{
DashType.Forward => transform.forward,
DashType.Backward => -transform.forward,
DashType.Left => -transform.right,
DashType.Right => transform.right,
DashType.InputVector => inputVector != Vector3.zero ? inputVector : transform.forward,
DashType.Random => new Vector3(Random.Range(-1f, 1f), 0f, Random.Range(-1f, 1f)).normalized,
_ => Vector3.zero
};
if (dashCoroutine != null)
{
StopCoroutine(dashCoroutine);
dashCoroutine = null;
}
dashCoroutine = DashCoroutine(dashDirection, dashData);
StartCoroutine(dashCoroutine);
}
private IEnumerator DashCoroutine(Vector3 direction, DashData dashData)
{
var startPosition = transform.position;
var targetDistance = dashData.Distance;
if (Physics.SphereCast(startPosition, controller.radius, direction, out var hit, targetDistance, Layers.WallOrObstacle))
{
targetDistance = hit.distance - controller.radius;
}
OnDash?.Invoke(direction);
controller.detectCollisions = false;
var endPosition = startPosition + direction * targetDistance;
var elapsedTime = 0f;
while (elapsedTime < dashData.Duration)
{
elapsedTime += Time.deltaTime;
var t = elapsedTime / dashData.Duration;
var lerpT = dashData.Easing != null ? dashData.Easing.Evaluate(t) : Mathf.SmoothStep(0f, 1f, t);
transform.position = Vector3.Lerp(startPosition, endPosition, lerpT);
if (!animHandler.IsPlayLayerBusy() && (dashData.Type == DashType.InputVector || dashData.Type == DashType.Forward))
{
SlerpRotate(Quaternion.LookRotation(direction), settings.IdleRotateSpeed);
}
yield return null;
}
transform.position = endPosition;
controller.detectCollisions = true;
dashCoroutine = null;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public UniTask UseDash(DashData dashData)
{
dashCts?.Cancel();
dashCts = CTSHelper.CreateLinkedCTS(CTSHelper.GlobalToken, skillSystem.EntityToken);
var dashDirection = dashData.Type switch
{
DashType.Forward => transform.forward,
DashType.Backward => -transform.forward,
DashType.Left => -transform.right,
DashType.Right => transform.right,
DashType.InputVector => inputVector != Vector3.zero ? inputVector : transform.forward,
DashType.Random => new Vector3(Random.Range(-1f, 1f), 0f, Random.Range(-1f, 1f)).normalized,
_ => Vector3.zero
};
return MovementAsync(dashDirection, dashData, dashCts.Token);
}
private async UniTask MovementAsync(Vector3 direction, DashData data, CancellationToken token)
{
var startPosition = transform.position;
var targetDistance = data.Distance;
if (Physics.SphereCast(startPosition, controller.radius, direction, out var hit, targetDistance, Layers.WallOrObstacle))
{
targetDistance = hit.distance - controller.radius;
}
OnDash?.Invoke(direction);
controller.detectCollisions = false;
var endPosition = startPosition + direction * targetDistance;
var elapsedTime = 0f;
while (elapsedTime < data.Duration)
{
if (token.IsCancellationRequested) break;
elapsedTime += Time.deltaTime;
var t = elapsedTime / data.Duration;
var lerpT = data.Easing != null ? data.Easing.Evaluate(t) : Mathf.SmoothStep(0f, 1f, t);
transform.position = Vector3.Lerp(startPosition, endPosition, lerpT);
if (!animHandler.IsPlayLayerBusy() && (data.Type == DashType.Forward || data.Type == DashType.InputVector))
{
SlerpRotate(Quaternion.LookRotation(direction), settings.IdleRotateSpeed);
}
await UniTask.Yield(PlayerLoopTiming.Update, token);
}
transform.position = endPosition;
controller.detectCollisions = true;
}
코루틴이었던 놈을 유니태스크로 바꿨는데 동작을 안 함
토큰이 캔슬됐나? 아님
중단점 찍어보면 와일문을 바로 빠져나가던데.. 그렇다해도
endPosition 위치로 이동은 되어야하는데 제자리에 있음
유니태스크로 바꾼 로직을 몬스터에 썼을 땐 또 제대로 동작함(캐릭터컨트롤러가 아닌 네브메쉬에이전트인 점만 다름)
뭐지? 진짜 모르겠음
흠 걍 플레이어는 코루틴 쓰는 걸로
고수님 코드 하나도 모르겟어요... 초보는 웁니다
같이 울죠
유니태스크 잘 모르긴 한데 return MovementAsync(dashDirection, dashData, dashCts.Token);에서 await 처리는 필요 없슴?? 태스크 작업에 필요할 것 같은 느낌인데..
넹 await를 넣으려면 return 없애고 UniTask 앞에 async 추가해야함
저게 문제였으면.. 몬스터도 대쉬가 안 나가야하는데... 흠 ㄹㅇ 모르겠넴 이거는.. GPT도 로직상으론 문제없고 디버깅 잘 해보라는 얘기만 함....
이건 정말 기능 필요한거면 디버거 중단점 찍고 f11인가 눌러보면서 한 줄씩 한번 보는 편이 해결이 빠를 것 같당
코루틴은 리턴안하는데, 유니태스크는 왜 리턴받냐 그리고 유니태스크 유즈대시는 왜 유니태스크 있음
나라면 유즈대시는 그냥 public void로 만들고 무브먼트 에이싱크는 유니태스크 보이드로 만들고, 쓸때 무브먼트 에이싱크.forget쓸것같은데
음 원래는 그 형태긴 했음
해결하셨나여? 제가 알려드려도 댐?
UseDash 함수 어떻게 호출하는지만 알려주세여
알려주세오 ㅠㅠ 코루틴으로 쓰고 있음 지금은
음 그러니까, UniTask로 바꾼 이후에 UseDash 함수를 호출할때 UniTask.Action(UseDash) 뭐 이런식으로 호출하고 있나여?
if (user.TryGetComponent<PlayerController>(out var playerController)) { playerController.OnDash += DashVFX; playerController.UseDash(dashData);
지금은 코루틴이라 .Forget();이 빠짐
제 생각부터 말하자면 UseDash함수는 UniTask 리턴하지 말고 void를 리턴하고, UseDash 함수 안에서 Unitask.Void(MovementAsync) 식으로 호출하세여 MovementAsync 함수는 UniTaskVoid 리턴하시구
엇 해볼게요 잠시만요..
MovementAsync가 파라미터가 많네여ㅎㅎ;; 애먹으실듯 핵심은 코루틴을 활용할땐 StartCoroutine 함수 쓰듯, UniTask를 시작시키는 놈은 UniTask.Action이나 UniTask.Void 같은 녀석임
StartCoroutine같은 역할을 하는 코드가 딱히 안보여서 말씀드렸읍니다 이게 정답이었으면 좋겠네여
몬스터에 썼을때 됐던 이유는 아무래도 Destination을 찝어줘서 어쨋든 이동을 해서가 아닌가 싶기두 하고... await 만날때까지 실행은 할테니
흠... 안 되네요.. UniTask.Void(async () => await MovementAsync(dashDirection, dashData, dashCts.Token)); 이렇게 하라고 하신게 맞나요;;?
채찍피티한테 "UseDash 함수를 Unitask.Void로 호출할 수 있도록 화끈하게 만져줘"라고 요청하셈 이게 가장 빠를듯
Void 안에는 파라미터 1개밖에 못받아서 지금 MovementAsync함수 파라미터 3개 받는게 문제가 되는군여... UseDash 함수를 처리하는게 낫겟네여 제가 원하는 정확한 함수 모양새는 Unitask.Void(UseDash, dashData) 입니다 UseDash 함수 기준으로여
유니태스크 좋긴 한데 그만큼 까다로운데... 왜 가시밭길을... 흐긓ㄱ 부디 잘 해결하시길
if (user.TryGetComponent(out var playerController)) { playerController.OnDash += DashVFX; UniTask.Void(playerController.UseDash, dashData); } public async UniTaskVoid UseDash(DashData dashData) private async UniTask MovementAsync(Vector3 direction, DashData data, CancellationToken token) 요래 바꿔봤는데.. 안 됨..
오! 제가 생각하는 모양새가 맞아요 이제 될겁니다. 혹시 MovementAsync에 await 붙이셨나여?
넹 안 붙이면 초록밑줄 그어서 붙였어요
이제 유니태스크는 확실하게 실행이 될텐데, 이후부터는 다른 문제겠네여.... 이제 코루틴을 완전히 대체한건 맞음ㅋㅋ
cts캔슬땜에 계속 날라가는거 같은데..
ㄴㄴ 토큰 부분 다 지우고도 해본..
이건 코루틴도 마찬가지로 계속 날리지않음?
맞음
ㅇㅎ.. 와일문을 바로 빠져나가고 transform.position = endPosition; 이 안먹힌다길래 걍 날라간줄..
엔드포지션 전후로 트랜스폼 로그찍고 데이터시트 제대로 받아오는지 로그찍는거 말곤 모르겟네
변수에 값은 다 들어가있는데.. 와일문을 바로 빠져나감
변수에 값 다 들어있는거 확인했어도 엔드포지션은 가야하는데 엔드포지션도 안가면 1. 누가 위치 돌려놓거나 2. 값을 못받아왔거나 이 두개 아니면 짐작가는게 없음
무브먼트 에이싱트에 어웨잇 걸고 어웨잇 아랫줄에 트랜스폼 로그찍어도 제자리임?
허.. 1번이었던 거 같네요........
아니.. 근데 여전히 모르겠슴. 아래는 예상 시나리오임1. 유니태스크에서 transform.position 값 변경2. 업데이트문에서 호출되는 기본 이동으로 덮음 controller.Move이거를1. 유니태스크에서 controller.Move 값 변경2. 업데이트문에서 호출되는 기본 이동으로 덮음 controller.Move (?)이건 왜 덮어쓰기가 안 된 거지..?
1. 코루틴에서 transform.position 값 변경 2. 업데이트문에서 호출되는 기본 이동으로 덮음 controller.Move ??? 1. 업데이트문에서 호출되는 기본 이동 controller.Move 2. 코루틴에서 transform.position 값 변경 흠.. 이건 이럴 수 있어 코루틴이 업데이트문 이후에 갱신하는 건가(?) 정말 모르겠다 ㄹㅇ로
어.. 왜 되지
transform.position = Vector3.Lerp(startPosition, endPosition, lerpT);이걸 var newPosition = Vector3.Lerp(startPosition, endPosition, lerpT); controller.Move(newPosition - transform.position);이렇게 바꾸니까 되는데아니 그럼 코루틴일 땐 왜 controller.Move 안 써도 됐던 거지설마 업데이트 동안에 controller.Move가 계속 호출되고 있어서 덮어씌어졌던 건가
오! 다행이네여 내 도움 약간 됐다 린정? ㅋㅋㅋ
아니네 나는 별 도움 안댔네... 시무룩
아닙니당.. 덕분에 유니태스크 정석적인 호출법을 배우게 됐슴..
CharacterController.Move 호출을 통한 이동과 transform.position 직접 할당의 차이 유니태스크와 코루틴의 서로 다른 업데이트 주기의 차이 이 넷의 콜라보였던 걸로....
업뎃 주기차이 이게 문제가 되는 경우 아주 많이 봄. 분명 로직상 문제는 없는데 절대 작동을 안함. 그래서 중간에 틱 딜레이 넣어보면 작동하는 경우가 많았음. 그래서 로직에 문제 없다고 확신이 들면 무조건 틱 딜레이부터 넣어봄.