#godot #gd-native #animation #tweening #api-bindings #dotween

nightly gdnative_tweener

将Unity第三方包DoTween(3rd party package for Unity)移植到Godot 3.5,使用GdNative

2个版本

0.5.9 2024年6月20日
0.5.8 2024年4月27日
0.4.0 2024年4月9日
0.3.1 2024年4月8日
0.1.0 2024年4月1日

#383游戏开发

Download history 712/week @ 2024-04-09 187/week @ 2024-04-16 363/week @ 2024-04-23 29/week @ 2024-04-30 1/week @ 2024-05-14 5/week @ 2024-05-21 5/week @ 2024-06-11 191/week @ 2024-06-18 8/week @ 2024-06-25 62/week @ 2024-07-23

每月 62 次下载

MIT 许可证

1MB
7K SLoC

Rust 4.5K SLoC // 0.0% comments Forge Config 2.5K SLoC Batch 12 SLoC

包含 (Windows DLL, 1MB) tester/Bin/gdnative_tweener.dll

gdnative_tweener是..

警告!

  • 此包尚未经过彻底测试,可能包含破坏游戏的错误。尽管如此,我每天都在所有项目中使用它,并承诺尽快修复任何报告的错误,至少到2025年7月。
  • 此包大部分没有文档,这个readme就是所有内容,并且由于作者是唯一已知的用户,它可能仍然保持如此。但接受添加文档的PR。
  • 此包需要Rust nightly版本,并使用如autotraits和negative impls等不稳定功能。

摘要

用法

当使用Godot的内置 SceneTreeTween 时,节点颜色缓动需要执行以下操作

fn tween_color(owner: Ref<Node2D>, color: Color, duration: f64) -> Result<SceneTreeTween> {
    let owner_tref = unsafe {
        owner.assume_safe_if_sane()
             .ok_or_else(|| Error("Owner is not sane, cannot create tween."))?
    };

    let tween =
        owner_tref.create_tween()
                  .ok_or_else(|| Error("Could not create tween."))?;

    let tween_tref = unsafe {
        tween.assume_safe()
    };

    tween_tref.tween_property(owner, "modulate", color, duration);

    return tween;
}

这相当多的样板代码,你可能经常这样做,具体取决于你的游戏中有多少动画。此库的目的是以更直观的方式实现相同的功能。以下是使用 gdnative_tweener 缓动节点颜色的方法

use gdnative_tweener::prelude::*;

fn tween_ref_wrapper_color(owner: Ref<Node2D>, color: Color, duration: f64) -> Result<TweenID<TweenProperty_Color>> {
    owner.do_color(color, duration)
	 .register()
}

// `do_color` is implemented on any of &T|Ref<T>|TRef<T>, where T: SubClass<CanvasItem>, this is because CanvasItem is the class that defines the property `modulate`, which `do_color` acts on.
fn tween_any_subclass_of_canvas_item(ref_sprite: Ref<Sprite>, tref_tilemap: TRef<TileMap>, control: &Control) -> Result<()> {
    let color = Color::from_rgb(0.8, 0.0, 0.8); // purple :3
    let duration = 0.69;

    let tween_id_of_ref = ref_sprite.do_color(color, duration).register()?;

    let tween_id_of_tref = tref_tilemap.do_color(color, duration).register()?;

    let tween_id = control.do_color(color, duration).register()?;

    Ok(())
}

请注意,与DoTween不同,我们需要在最后调用register()。代码register()尝试访问TweensController自动加载,将其插入到内部列表中。它还返回一个Result<TweenID>,您可以使用它来稍后访问缓动,检查缓动是否存活,其状态等。如果自动加载不可访问(这可能发生在它不存在或已经被别处借用的情况下),则操作将失败。

gdnative_tweener提供了多种方法来配置您缓动的行为,尽管没有文档说明,但名称相当直观,类似于DoTween。您应该在注册缓动之前进行所有配置,注册后修改缓动可能会影响性能,因为这需要获取TweensController自动加载的锁。我不建议在主线程之外尝试注册/访问缓动。

以下是一些示例

let owner: Ref<Node2D> = ..;
let mut tween = owner.do_move_x(2000.0, 5.0);

// To mimic TweenProperty::as_relative()
let origin = 0.0; // since relative tweens don't have a starting point, the origin parameter is necessary for the tween to compare how much it needs to move between each frame
tween = tween.as_relative(origin);

// To mimic TweenProperty::from_current(), no need to do anything, that's the default behavior,
// instead, if you want to set a specific starting point:
tween = tween.starting_at(500.0);

// To mimic TweenProperty::set_delay(f64);
tween = tween.with_delay(10.0);

// SpeedBased is also implemented:
let speed = 100.0; // Speed is always in units per second, 100. speed means position:x increases by 100 each second.
tween = tween.as_speed_based(speed);

您可以将所有这些方法链接起来

let tween_id =
	node.do_global_position(Vector2::new(1920., 1080.), 5.0)
		.with_delay(10.0)
		.starting_at(Vector2::new(0., 0.))
		.looped(10)
		.when_finished(node, "print", vec!["Tween finished!".to_variant()])
		.register()?;

属性缓动只是DoProperty特质的包装。代码do_property自动将节点绑定到缓动,就像Node::create_tween一样,这意味着当节点被删除时,缓动将自动“死亡”。

DoProperty使用call_deferred("set_indexed"),因此属性路径也是有效的

// Tween only the Z position
let tween = owner.do_property("position:z", 20., 10.);

DoProperty接受泛型值,只要它们实现了_Lerp + FromVariant + ToVariant

let my_custom_property = "..";
let my_custom_end_val = CustomStruct {..};
let duration = 5.0;

// the only difference is that the method is called do_property_var()
let tween = owner.do_property_var(my_custom_property, my_custom_end_val, duration);

您还可以缓动方法

// Imagine you have a method like this...
#[method]
fn _set_fill(&self, #[base] owner: &Range, value: f64) {
	owner.set_value(value);
}

// You can tween it like this
let start = 0.;
let end = 1.;
let duration = 8.;
let tween = owner.do_method("_set_fill", start, end, duration);

如果您只需要在延迟后调用一次方法,您可以使用

#[method]
fn _start_game(&mut self, player_name: String, difficulty: Difficulty) {
	...
}

let player_name = "Houtamelo";
let difficulty = Difficulty::GameDeveloper;
let delay = 24.;
let tween = owner.do_callback("_start_game", vec![player_name.to_variant(), difficulty.to_variant()], delay);

永远不要忘记注册您的缓动!否则它们将被丢弃

let id = tween.register()?;

我们还有序列,它们的工作方式与DoTween非常相似

let mut sequence = Sequence::new();
sequence.append(owner.do_move_x(640.0, 5.0));
sequence.join(owner.do_fade(1.0, 4.0));
sequence.append(owner.do_global_move(Vector2::new(124., 256.));
sequence.insert(8.0, owner.do_scale(Vector2::new(10., 10.));

let id = sequence.register()?;

需要终止一个缓动吗?

let id: TweenID<TweenCallback> = ..;
id.kill();

// Same for sequences
let sequence_id: SequenceID = ..;
sequence_id.kill();

需要立即完成一个缓动吗?

tween_id.complete();
sequence_id.complete();

了解...

  • gdnative_tweener以任何方式与Godot的内置缓动交互,它是一个独立的NativeScript,在它的_process(f64)_physics_process(f64)虚拟方法中处理已注册的缓动。
  • 缓动执行的每个交互都是以“延迟”方式完成的...(“set_property_deferred”,“call_deferred”)

设置

设置过程假设您已经熟悉GDNative的工作方式。

第1步

gdnative_tweener添加到您的项目依赖项中:运行cargo add gdnative_tweener或将以下行添加到您的Cargo.toml中:gdnative_tweener = "0.3"

您很可能会想使用最新版本,因为它将包含最新的错误修复。

第2步

在您的库的初始化(在gdnative模板中:rust/src/lib.rs)中注册TweenController

fn init(handle: InitHandle) {
	handle.add_class::<gdnative_tweener::prelude::TweensController>();
}

第3步

在您的 Godot 项目中,为 TweensController 类创建一个 NativeScript:![图片](https://img.gs/czjpqfbdkz/full/https://github.com/Houtamelo/gdnative_tweener/assets/88971943/da0f6b81-c76f-4b75-b56d-4059a2d8246a "图片" width="504" height="431")

步骤 4

TweensController 类添加到项目的自动加载中,节点命名为 "tweens_controller":![图片](https://img.gs/czjpqfbdkz/full/https://github.com/Houtamelo/gdnative_tweener/assets/88971943/83bd22ef-fe9a-4380-a738-a958f0492a5b "图片" width="800" height="135")

警告:节点名称必须是 "tweens_controller",否则在尝试注册缓动时将收到错误。

帮助

在 GitHub 上创建一个问题或向我发送 Discord 消息:houtamelo

依赖关系

~13–21MB
~321K SLoC