-
-
Save mesqueeb/bf3890bf9117810f7468053e737cfafb to your computer and use it in GitHub Desktop.
// | |
// Entity+MoveAsync.swift | |
// | |
// Created by Drew Olbrich on 1/15/24. | |
// Copyright © 2024 Lunar Skydiving LLC. All rights reserved. | |
// | |
// MIT License | |
// | |
// Permission is hereby granted, free of charge, to any person obtaining a copy | |
// of this software and associated documentation files (the "Software"), to deal | |
// in the Software without restriction, including without limitation the rights | |
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
// copies of the Software, and to permit persons to whom the Software is | |
// furnished to do so, subject to the following conditions: | |
// | |
// The above copyright notice and this permission notice shall be included in all | |
// copies or substantial portions of the Software. | |
// | |
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
// SOFTWARE. | |
// | |
import Foundation | |
import RealityKit | |
import Combine | |
extension Entity { | |
/// Asynchronously moves an entity over a period of time to a new location given by | |
/// a transform. | |
/// | |
/// - Parameters: | |
/// - target: A ``Transform`` instance that indicates the new location. | |
/// | |
/// - referenceEntity: The entity that defines a frame of reference. Set | |
/// this to `nil` to indicate world space. | |
/// | |
/// - duration: The time in seconds over which the move should occur. | |
/// | |
/// - timingFunction: A timing function that controls the progress of the | |
/// animation. | |
@MainActor func moveAsync(to target: Transform, relativeTo referenceEntity: Entity?, duration: TimeInterval, timingFunction: AnimationTimingFunction = .default) async { | |
guard let scene else { | |
return | |
} | |
let animationPlaybackController = move(to: target, relativeTo: referenceEntity, duration: duration, timingFunction: timingFunction) | |
let publisher = scene.publisher(for: AnimationEvents.PlaybackCompleted.self, on: self) | |
await withCheckedContinuation { continuation in | |
Task { | |
for await event in publisher.values { | |
if event.playbackController == animationPlaybackController { continuation.resume() } | |
} | |
} | |
} | |
} | |
} |
Thanks!, those seem like good changes.
I was unable to reproduce the Xcode warning, but I haven't attempted to convert my project to Swift 6 yet.
Is that probably why?
Do you mind if I merge your changes in with my original code? I'll credit you in comments.
@drewolbrich For sure! Thanks a lot : )
Yeah, once you set the Swift Language version to Swift 6 you're basically opening up yourself to a week of pulling out your hairs. : P
@drewolbrich I just realise now that the comment says:
/// - Returns: An ``AnimationPlaybackController`` instance that you use to control the animation playback.
But given that this is async, the only timing we could return it would be after the animation finishes. :P So it's probably not useful at that point and I have removed that comment from the docs just now.
Thanks, I've updated the original gist based on your changes.
Good catch about the doc comment! I think that was left over from an earlier version of the function I wrote, which was not async.
I've added you to my app's credits.
: - )
I've been hesitant to update to Swift 6 because of the time suck. Also I was under the impression that even inside Apple, they're still trying to sort out what the best practices are. I figured I'd wait until Swift 7 when the fiddly edge cases have been addressed, rather than discovering them myself.
@drewolbrich
Fellow visionOS dev here! : D
I've slightly revised your GIST to take care of the race condition pointed out by Xcode:
I'm not sure if this is an actual issue in the original code, but it's always nice to get rid of warnings :P
I've also limited the publisher to
on: self
so it only watches the entity we're executing it on, just in case!Great work on your other gists! I've learned some stuff here and there reading through them. ;)