I have this animation function in Swift6 RealityKit application. It puts given entity softly in scene. It works.
But I am getting Capture of 'simpleMaterial' with non-sendable type 'SimpleMaterial' in a '@Sendable' closure warning. How can we get rid of it.
func fadeInText(entity: ModelEntity, duration: TimeInterval = 1) {
guard var simpleMaterial = entity.model?.materials.first as? SimpleMaterial else { return }
let steps = 60
let interval = duration / Double(steps)
let startTime = CACurrentMediaTime()
Timer.scheduledTimer(withTimeInterval: interval, repeats: true) { t in
let elapsed = CACurrentMediaTime() - startTime
let progress = min(elapsed / duration, 1.0)
let alpha = progress
Task { @MainActor in
simpleMaterial.color.tint = simpleMaterial.color.tint.withAlphaComponent(CGFloat(alpha))
entity.model?.materials = [simpleMaterial]
}
if progress >= 1.0 {
t.invalidate()
}
}
}
-
when "guard var simpleMaterial = entity.model?.materials.first as? SimpleMaterial else { return }" placed in Task warning disappears but is it OK?Hope– Hope2025年07月11日 10:19:25 +00:00Commented Jul 11, 2025 at 10:19
-
Yes, it's OK. But why do you have a Task here at all?matt– matt2025年07月11日 12:38:54 +00:00Commented Jul 11, 2025 at 12:38
1 Answer 1
when "guard var simpleMaterial = entity.model?.materials.first as? SimpleMaterial else { return }" placed in Task warning disappears but is it OK?
Yes, it's a good workaround. But the problem here is really that the line
Task { @MainActor in
is unnecessary. You don't need a Task here. I presume you are doing this because you want to ensure that the code in the inner closure executes on the main actor. But there is no need for this, because when your timer fires, the entire timer closure will be called on the main actor anyway, so you don't need to switch to the main actor.
If the compiler doesn't realize that the closure will be called on the main actor, just tell it that it will be; instead of saying
Task { @MainActor in
say
MainActor.assumeIsolated {
Personally, I would wrap the entire timer closure in this structure:
Timer.scheduledTimer(withTimeInterval: interval, repeats: true) { t in
MainActor.assumeIsolated {