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

Expression2无人机脚本开发:地图绕飞避障+聊天指令锁敌返航

Expression2 无人机脚本修复:解决撞墙问题+添加返航功能

问题说明

需要开发一款Expression2(E2)芯片脚本,实现两个核心功能:

  • 无人机在地图中自主绕飞,全程不碰撞墙体
  • 通过聊天指令设置目标玩家名称后,无人机向该玩家位置返航

现有脚本存在两个问题:

  1. 无人机频繁撞墙
  2. 缺失玩家指定返航功能

现有代码

@inputs EGP:wirelink
@persist [UAV]:entity
@persist [AngPull Speed RngLength]:number
@persist RotAng:angle
@persist [Positions]:table

interval(10)

if(first()){
    AngPull = 1
    Speed = 2 #Multiplier
    RngLength = 8000
    
    #EGP = spawnEgp("models/hunter/plates/plate2x2.mdl",entity():pos(),ang(),1):wirelink()

    propSpawnUndo(0)
    if(EGP){
        entity():setPos(entity():toWorld(vec(0,0,-10)))
    }
    UAV = propSpawn("models/xqm/jetbody3_s2.mdl",entity():toWorld(vec(0,0,30)),entity():angles(),0)
    UAV:setColor(vec(randint(40,100)))
    UAV:propGravity(0)
    
    UAV:setTrails(30,30,1,"trails/smoke",vec(100),255)
    
    rangerPersist(1)
    rangerFilter(UAV)
    
    RotAng = ang()
    
    UAV:soundPlay(1,inf(),"Phx.HoverLight")
    
    noCollideAll(UAV,1)#so we dont kill players
}

if(owner():keyZoom()){UAV:propFreeze(0)}

if(changed(EGP)){
    if(EGP){
        entity():setPos(entity():toWorld(vec(0,0,-10)))
    }else{
        entity():setPos(entity():toWorld(vec(0,0,10)))
    }
}

Ranger = rangerOffset(RngLength,UAV:pos(),UAV:right())
Height = abs(-11519.968750 - UAV:pos()[3])

if(Ranger:hit()){RotAng+=ang(1,1*((RngLength-Ranger:distance())/(RngLength)),0),Mul=((RngLength-Ranger:distance())/(RngLength/150))*Speed}else{Mul=20*Speed}

if(Height<1500){RotAng+=ang(0,0,-1)}else{RotAng = RotAng:setRoll(0)}

timer("soundplay",5000)

soundPitch(1,UAV:vel():length())

UAV:applyForce(UAV:right()*UAV:mass()*Mul - UAV:vel())
UAV:applyTorque( ( ( (UAV:toLocalAxis(rotationVector(quat( RotAng )/quat(UAV)))) *200-UAV:angVelVector()*20)*UAV:inertia() ) *AngPull)

foreach(Key,Ply:entity = players()){
    local Ranger = rangerOffset(100000,UAV:pos(),Ply:pos()-UAV:pos())
    if(Ranger:entity() == Ply){
        Positions[Ply:steamID(),vector] = Ply:pos()
        
        EGP:egpBox(Key,vec2(clamp(Ply:pos()[1]/50+200,0,500), clamp(Ply:pos()[2]/50+200,0,500) ),vec2(7.5))
        EGP:egpColor(Key,teamColor(Ply:team()))
        EGP:egpTextLayout(Key+20,Ply:name(),vec2(clamp(Ply:pos()[1]/50+200,0,500), clamp(Ply:pos()[2]/50+200,0,500) ),vec2(100,50))
        EGP:egpFont(Key+20,"",12)
    }
}

if(changed(UAV)){
    if(!UAV){
        selfDestructAll()
    }
}

修复方案

1. 撞墙问题修复

原脚本仅检测无人机右侧障碍物,且转向逻辑简单,导致无人机无法提前避让前方/左侧障碍,容易卡墙。修改点:

  • 增加前、左、右三个方向的障碍物检测
  • 优化转向权重:障碍物越近,转向幅度越大
  • 调整高度控制逻辑,避免因固定高度值导致的异常升降

2. 返航功能添加

  • 监听聊天指令!return [玩家名],设置返航目标
  • 增加状态变量区分绕飞模式和返航模式
  • 返航时向目标玩家位置移动,到达指定距离后悬停

修复后完整代码

@inputs EGP:wirelink
@persist [UAV TargetPlayer]:entity
@persist [AngPull Speed RngLength ReturnDistance]:number
@persist RotAng:angle
@persist [Positions]:table
@persist ReturnMode:boolean  # 返航状态标记

interval(10)

if(first()){
    AngPull = 1.2
    Speed = 2.5  # 优化速度系数
    RngLength = 6000  # 缩短检测距离,提前反应
    ReturnDistance = 500  # 到达目标附近后悬停的距离
    ReturnMode = false
    
    propSpawnUndo(0)
    if(EGP){
        entity():setPos(entity():toWorld(vec(0,0,-10)))
    }
    UAV = propSpawn("models/xqm/jetbody3_s2.mdl",entity():toWorld(vec(0,0,30)),entity():angles(),0)
    UAV:setColor(vec(randint(40,100)))
    UAV:propGravity(0)
    
    UAV:setTrails(30,30,1,"trails/smoke",vec(100),255)
    
    rangerPersist(1)
    rangerFilter(UAV)
    
    RotAng = ang()
    
    UAV:soundPlay(1,inf(),"Phx.HoverLight")
    
    noCollideAll(UAV,1)
}

# 监听聊天指令设置返航目标
if(owner():chat()){
    local Msg = owner():chatText()
    if(Msg:sub(1,7) == "!return "){
        local TargetName = Msg:sub(8)
        foreach(Ply:entity = players()){
            if(Ply:name():lower() == TargetName:lower()){
                TargetPlayer = Ply
                ReturnMode = true
                print("已设置返航目标: "..Ply:name())
                break
            }
        }
        if(!TargetPlayer){
            print("未找到玩家: "..TargetName)
        }
    }
    # 取消返航指令
    if(Msg == "!cancelreturn"){
        ReturnMode = false
        TargetPlayer = null
        print("已取消返航")
    }
}

# 返航模式逻辑
if(ReturnMode && TargetPlayer:isValid()){
    local TargetPos = TargetPlayer:pos()
    # 计算无人机到目标的方向向量
    local Dir = (TargetPos - UAV:pos()):normalize()
    local Distance = (TargetPos - UAV:pos()):length()
    
    # 到达目标附近后悬停
    if(Distance <= ReturnDistance){
        Mul = 0
        # 调整朝向目标
        RotAng = Dir:toAngle()
    }else{
        Mul = Speed * 15
        # 朝目标方向转向
        RotAng = Dir:toAngle()
    }
    
    # 高度保持:跟随玩家高度
    local HeightDiff = TargetPos[3] - UAV:pos()[3]
    if(HeightDiff > 200){
        RotAng:add(ang(0,0,0.5))
    }else if(HeightDiff < -200){
        RotAng:add(ang(0,0,-0.5))
    }
}else{
    # 绕飞模式:多方向障碍物检测
    local RangerFront = rangerOffset(RngLength, UAV:pos(), UAV:forward())
    local RangerRight = rangerOffset(RngLength, UAV:pos(), UAV:right())
    local RangerLeft = rangerOffset(RngLength, UAV:pos(), -UAV:right())
    
    Mul = 20 * Speed
    RotAng:add(ang(0, 0.2, 0))  # 基础绕飞转向
    
    # 前方障碍物:大幅左转
    if(RangerFront:hit()){
        local DistRatio = (RngLength - RangerFront:distance())/RngLength
        RotAng:add(ang(0, 0, DistRatio * 8))
        Mul = Speed * (10 - DistRatio * 8)
    }
    
    # 右侧障碍物:左转
    if(RangerRight:hit()){
        local DistRatio = (RngLength - RangerRight:distance())/RngLength
        RotAng:add(ang(0, 0, DistRatio * 5))
        Mul = Speed * (15 - DistRatio * 5)
    }
    
    # 左侧障碍物:右转
    if(RangerLeft:hit()){
        local DistRatio = (RngLength - RangerLeft:distance())/RngLength
        RotAng:add(ang(0, 0, -DistRatio * 5))
        Mul = Speed * (15 - DistRatio * 5)
    }
    
    # 高度控制:保持在地面上方1500单位(可根据地图调整)
    local GroundPos = UAV:pos()
    GroundPos[3] = -11519.968750
    local Height = (UAV:pos() - GroundPos):length()
    if(Height < 1200){
        RotAng:add(ang(0,0,-0.8))
    }else if(Height > 1800){
        RotAng:add(ang(0,0,0.8))
    }
}

# 通用运动控制
UAV:applyForce(UAV:right()*UAV:mass()*Mul - UAV:vel())
UAV:applyTorque( ( ( (UAV:toLocalAxis(rotationVector(quat( RotAng )/quat(UAV)))) *200-UAV:angVelVector()*20)*UAV:inertia() ) *AngPull)

# EGP玩家显示(保留原逻辑)
if(EGP){
    foreach(Key,Ply:entity = players()){
        local Ranger = rangerOffset(100000,UAV:pos(),Ply:pos()-UAV:pos())
        if(Ranger:entity() == Ply){
            Positions[Ply:steamID(),vector] = Ply:pos()
            
            local ScreenPos = vec2(clamp(Ply:pos()[1]/50+200,0,500), clamp(Ply:pos()[2]/50+200,0,500))
            EGP:egpBox(Key,ScreenPos,vec2(7.5))
            EGP:egpColor(Key,teamColor(Ply:team()))
            EGP:egpTextLayout(Key+20,Ply:name(),ScreenPos,vec2(100,50))
            EGP:egpFont(Key+20,"",12)
        }
    }
}

# 无人机销毁处理
if(changed(UAV)){
    if(!UAV){
        selfDestructAll()
    }
}

# 音效处理(保留原逻辑)
timer("soundplay",5000)
soundPitch(1,UAV:vel():length())

使用说明

  1. 设置返航:在聊天框输入!return [玩家名称],无人机将向目标玩家飞去
  2. 取消返航:输入!cancelreturn,无人机恢复绕飞模式
  3. 撞墙避让:无人机现在会检测前、左、右三个方向的障碍,提前调整方向避免碰撞

内容的提问来源于stack exchange,提问作者homura-akemi-f02-22

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 01:31:04