You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Rust中消除代码重复,实现处理各类实体的泛型函数

用Rust泛型统一实体碰撞检测实现

核心思路

通过定义一个trait提取所有可碰撞实体的共性,再基于这个trait编写泛型碰撞检测函数,替代多个特定实体的重复函数。

步骤实现

1. 定义可碰撞实体的Trait

先创建Collidable trait,包含碰撞所需的核心方法:获取位置、半径,以及销毁实体的kill方法:

// 假设你已有Position结构体及distance方法
#[derive(Debug, Clone, Copy)]
struct Position {
    x: f32,
    y: f32,
}

impl Position {
    fn distance(&self, other: &Self) -> f32 {
        ((self.x - other.x).powi(2) + (self.y - other.y).powi(2)).sqrt()
    }
}

// 可碰撞实体的统一Trait
trait Collidable {
    fn position(&self) -> &Position;
    fn radius(&self) -> f32;
    fn kill(&mut self);
}

2. 让所有实体实现Trait

给Asteroid、Player、Laser分别实现Collidable trait,对齐它们的碰撞相关行为:

// 假设你的实体基础结构如下
struct Entity {
    position: Position,
    // 其他通用字段...
}

struct Asteroid {
    entity: Entity,
    radius: f32,
    alive: bool,
}

struct Player {
    entity: Entity,
    radius: f32,
    alive: bool,
}

struct Laser {
    entity: Entity,
    radius: f32,
    alive: bool,
}

// Asteroid实现Collidable
impl Collidable for Asteroid {
    fn position(&self) -> &Position {
        &self.entity.position
    }

    fn radius(&self) -> f32 {
        self.radius
    }

    fn kill(&mut self) {
        self.alive = false;
        // 其他销毁逻辑...
    }
}

// Player实现Collidable
impl Collidable for Player {
    fn position(&self) -> &Position {
        &self.entity.position
    }

    fn radius(&self) -> f32 {
        self.radius
    }

    fn kill(&mut self) {
        self.alive = false;
        // 其他销毁逻辑...
    }
}

// Laser实现Collidable
impl Collidable for Laser {
    fn position(&self) -> &Position {
        &self.entity.position
    }

    fn radius(&self) -> f32 {
        self.radius
    }

    fn kill(&mut self) {
        self.alive = false;
        // 其他销毁逻辑...
    }
}

3. 编写泛型碰撞检测函数

不同类型实体间的碰撞

处理两个不同实体集合的碰撞逻辑:

pub fn check_collision_between<T: Collidable, U: Collidable>(entities_a: &mut Vec<T>, entities_b: &mut Vec<U>) {
    for a in entities_a.iter_mut() {
        for b in entities_b.iter_mut() {
            let distance = a.position().distance(b.position());
            if distance < a.radius() + b.radius() {
                a.kill();
                b.kill();
            }
        }
    }
}

同类型实体间的碰撞

处理同一实体集合内的碰撞,需要跳过自身避免误判:

pub fn check_collision_within<T: Collidable + PartialEq>(entities: &mut Vec<T>) {
    for i in 0..entities.len() {
        for j in (i + 1)..entities.len() {
            let a = &mut entities[i];
            let b = &mut entities[j];
            let distance = a.position().distance(b.position());
            if distance < a.radius() + b.radius() {
                a.kill();
                b.kill();
            }
        }
    }
}

4. 替换原有函数调用

现在可以用这两个泛型函数替代所有特定场景的碰撞检测:

// 替代小行星与玩家的碰撞检测
check_collision_between(asteroids, players);

// 替代玩家间的碰撞检测
check_collision_within(players);

// 替代激光与玩家的碰撞检测
check_collision_between(lasers, players);

// 替代激光与小行星的碰撞检测
check_collision_between(lasers, asteroids);

补充说明

  • 泛型方案属于轻量重构,无需引入ECS框架,适合中小规模项目或快速迭代场景。
  • 若后续实体复杂度提升、需要更灵活的属性组合,ECS依然是更优选择,它能进一步解耦实体的属性与行为。

内容的提问来源于stack exchange,提问作者user3453345

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 14:20:40