首先打开script editor如下图 复制下面这个代码(注意修改相关路径为读者本地的),并运行如下图

js
#!/usr/bin/env python3
"""
Isaac Sim 4.5 - 简化版:导入机器人和创建LightBeam传感器
"""
import omni
import omni.kit.commands
from omni.isaac.core.utils.stage import add_reference_to_stage
from omni.isaac.core.utils.extensions import enable_extension
from pxr import Gf, Sdf, UsdLux, UsdPhysics
import os
import asyncio
# ==================== 配置部分 ====================
USERNAME = os.getenv('USER') or 'user'
# 路径配置
ISAAC_ASSETS_BASE = f"/home/{USERNAME}/isaacsim_assets/Assets/Isaac/4.5"
ROBOT_USD_PATH = os.path.join(ISAAC_ASSETS_BASE, "Isaac/Robots/iRobot/create_3_with_arm.usd")
ROBOT_PRIM_PATH = "/World/create3_robot"
# 传感器配置
SENSORS_CONFIG = [
# 底部高度传感器 - 4个方向
{
"name": "front_bottom",
"relative_position": [0, 0, 0.1],
"min_range": 0.5,
"max_range": 8.0,
"num_rays": 2,
"curtain_length": 0.05,
"forward_axis": [1, 0, 0]
},
{
"name": "back_bottom",
"relative_position": [0, 0, 0.1],
"min_range": 0.5,
"max_range": 8.0,
"num_rays": 2,
"curtain_length": 0.05,
"forward_axis": [-1, 0, 0]
},
{
"name": "left_bottom",
"relative_position": [0, 0, 0.1],
"min_range": 0.5,
"max_range": 8.0,
"num_rays": 2,
"curtain_length": 0.05,
"forward_axis": [0, 1, 0]
},
{
"name": "right_bottom",
"relative_position": [0, 0, 0.1],
"min_range": 0.5,
"max_range": 8.0,
"num_rays": 2,
"curtain_length": 0.05,
"forward_axis": [0, -1, 0]
},
# 顶部高度传感器 - 4个方向
{
"name": "front_top",
"relative_position": [0, 0, 0.9],
"min_range": 1,
"max_range": 8.0,
"num_rays": 2,
"curtain_length": 0.05,
"forward_axis": [1, 0, 0]
},
{
"name": "back_top",
"relative_position": [0, 0, 0.9],
"min_range": 0.5,
"max_range": 8.0,
"num_rays": 2,
"curtain_length": 0.05,
"forward_axis": [-1, 0, 0]
},
{
"name": "left_top",
"relative_position": [0, 0, 0.9],
"min_range": 0.5,
"max_range": 8.0,
"num_rays": 2,
"curtain_length": 0.05,
"forward_axis": [0, 1, 0]
},
{
"name": "right_top",
"relative_position": [0, 0, 0.9],
"min_range": 0.5,
"max_range": 8.0,
"num_rays": 2,
"curtain_length": 0.05,
"forward_axis": [0, -1, 0]
}
]
print("🤖 开始导入机器人和创建传感器...")
# ==================== 基础设置 ====================
def setup_basic_scene():
"""设置基础场景"""
print("🔧 设置基础场景...")
stage = omni.usd.get_context().get_stage()
# 创建物理场景
physics_scene_path = "/World/physicsScene"
if not stage.GetPrimAtPath(physics_scene_path):
UsdPhysics.Scene.Define(stage, Sdf.Path(physics_scene_path))
print("✅ 物理场景创建成功")
# 添加光照
light_path = "/World/DistantLight"
if not stage.GetPrimAtPath(light_path):
distantLight = UsdLux.DistantLight.Define(stage, Sdf.Path(light_path))
distantLight.CreateIntensityAttr(1000)
print("✅ 光照创建成功")
return stage
def import_robot():
"""导入机器人模型"""
print("🤖 导入机器人模型...")
if not os.path.exists(ROBOT_USD_PATH):
print(f"❌ 机器人文件不存在: {ROBOT_USD_PATH}")
print("💡 请检查路径配置")
return False
try:
add_reference_to_stage(usd_path=ROBOT_USD_PATH, prim_path=ROBOT_PRIM_PATH)
print(f"✅ 机器人导入成功: {ROBOT_PRIM_PATH}")
return True
except Exception as e:
print(f"❌ 机器人导入失败: {e}")
return False
def create_lightbeam_sensors():
"""创建所有LightBeam传感器"""
print("📡 创建LightBeam传感器...")
# 启用传感器扩展
enable_extension("isaacsim.sensors.physx")
created_sensors = []
for sensor_config in SENSORS_CONFIG:
sensor_name = sensor_config["name"]
sensor_path = f"{ROBOT_PRIM_PATH}/sensors/{sensor_name}"
print(f"🔧 创建传感器: {sensor_name}")
try:
result, sensor = omni.kit.commands.execute(
"IsaacSensorCreateLightBeamSensor",
path=sensor_path,
parent=None, # 不指定父级,稍后手动连接
min_range=sensor_config["min_range"],
max_range=sensor_config["max_range"],
translation=Gf.Vec3d(
sensor_config["relative_position"][0],
sensor_config["relative_position"][1],
sensor_config["relative_position"][2]
),
orientation=Gf.Quatd(1, 0, 0, 0),
forward_axis=Gf.Vec3d(
sensor_config["forward_axis"][0],
sensor_config["forward_axis"][1],
sensor_config["forward_axis"][2]
),
num_rays=sensor_config["num_rays"],
curtain_length=sensor_config["curtain_length"],
)
if result:
created_sensors.append(sensor_name)
print(f"✅ {sensor_name} 传感器创建成功")
else:
print(f"❌ {sensor_name} 传感器创建失败")
except Exception as e:
print(f"❌ {sensor_name} 传感器创建异常: {e}")
print(f"📊 总共创建了 {len(created_sensors)} 个传感器")
return created_sensors
# ==================== 主要执行函数 ====================
async def main():
"""主要执行函数"""
try:
# 1. 设置场景
stage = setup_basic_scene()
# 2. 导入机器人
if not import_robot():
print("❌ 机器人导入失败,停止执行")
return
# 等待导入完成
await omni.kit.app.get_app().next_update_async()
# 3. 创建传感器
created_sensors = create_lightbeam_sensors()
if created_sensors:
print(f"\n✅ 成功创建 {len(created_sensors)} 个传感器")
print("📋 创建的传感器列表:")
for sensor_name in created_sensors:
sensor_path = f"{ROBOT_PRIM_PATH}/sensors/{sensor_name}"
print(f" 📡 {sensor_name}: {sensor_path}")
print("\n💡 接下来请您手动:")
print("1. 在Stage面板中找到机器人和传感器")
print("2. 为每个传感器创建Fixed Joint连接到机器人")
print("3. 点击'Play'按钮测试传感器")
else:
print("❌ 没有成功创建任何传感器")
except Exception as e:
print(f"❌ 执行失败: {e}")
import traceback
traceback.print_exc()
# 运行主函数
asyncio.ensure_future(main())
print("🚀 脚本开始执行...")
运行后输出如下图
手动加一个地板用于测试,最后删掉地板资源即可

再将下面代码覆盖到script editor中,运行
js
#!/usr/bin/env python3
"""
Isaac Sim 4.5 - Action Graph光线可视化脚本
为8个LightBeam传感器创建可视化Action Graph
"""
import omni
import omni.graph.core as og
from omni.isaac.core.utils.extensions import enable_extension
import asyncio
# ==================== 配置部分 ====================
ROBOT_PRIM_PATH = "/World/create3_robot"
# 传感器名称列表
SENSOR_NAMES = [
"front_bottom", "back_bottom", "left_bottom", "right_bottom",
"front_top", "back_top", "left_top", "right_top"
]
# 颜色配置 - 不同方向和层级使用不同颜色
COLOR_CONFIG = {
# 底层传感器 - 深色系
"front_bottom": [1.0, 0.0, 0.0, 1.0], # 红色
"back_bottom": [0.0, 0.0, 1.0, 1.0], # 蓝色
"left_bottom": [0.0, 1.0, 0.0, 1.0], # 绿色
"right_bottom": [1.0, 1.0, 0.0, 1.0], # 黄色
# 顶层传感器 - 浅色系
"front_top": [1.0, 0.5, 0.5, 1.0], # 浅红色
"back_top": [0.5, 0.5, 1.0, 1.0], # 浅蓝色
"left_top": [0.5, 1.0, 0.5, 1.0], # 浅绿色
"right_top": [1.0, 1.0, 0.5, 1.0], # 浅黄色
}
print("🎨 开始创建Action Graph可视化...")
def enable_required_extensions():
"""启用必要的扩展"""
print("🔧 启用必要扩展...")
extensions = [
"isaacsim.sensors.physx",
"isaacsim.util.debug_draw",
"omni.graph.action",
"omni.graph.core"
]
for ext in extensions:
try:
enable_extension(ext)
print(f"✅ {ext} 扩展已启用")
except Exception as e:
print(f"⚠️ {ext} 扩展启用失败: {e}")
def create_single_sensor_visualization(sensor_name):
"""为单个传感器创建可视化Action Graph"""
sensor_path = f"{ROBOT_PRIM_PATH}/sensors/{sensor_name}"
graph_path = f"/ActionGraph_{sensor_name}_Viz"
print(f"🎨 创建 {sensor_name} 的可视化图表...")
# 获取颜色配置
color = COLOR_CONFIG.get(sensor_name, [1.0, 0.0, 0.0, 1.0])
try:
# 检查传感器是否存在
stage = omni.usd.get_context().get_stage()
if not stage.GetPrimAtPath(sensor_path):
print(f"❌ 传感器不存在: {sensor_path}")
return False
# 创建Action Graph
(action_graph, new_nodes, _, _) = og.Controller.edit(
{"graph_path": graph_path, "evaluator_name": "execution"},
{
og.Controller.Keys.CREATE_NODES: [
("OnPlaybackTick", "omni.graph.action.OnPlaybackTick"),
("IsaacReadLightBeam", "isaacsim.sensors.physx.IsaacReadLightBeam"),
("DebugDrawRayCast", "isaacsim.util.debug_draw.DebugDrawRayCast"),
],
og.Controller.Keys.SET_VALUES: [
("IsaacReadLightBeam.inputs:lightbeamPrim", sensor_path),
("DebugDrawRayCast.inputs:beamWidth", 0.02), # 光束宽度
("DebugDrawRayCast.inputs:color", color), # 光束颜色
],
og.Controller.Keys.CONNECT: [
("OnPlaybackTick.outputs:tick", "IsaacReadLightBeam.inputs:execIn"),
("IsaacReadLightBeam.outputs:execOut", "DebugDrawRayCast.inputs:exec"),
("IsaacReadLightBeam.outputs:beamOrigins", "DebugDrawRayCast.inputs:beamOrigins"),
("IsaacReadLightBeam.outputs:beamEndPoints", "DebugDrawRayCast.inputs:beamEndPoints"),
("IsaacReadLightBeam.outputs:numRays", "DebugDrawRayCast.inputs:numRays"),
],
},
)
print(f"✅ {sensor_name} 可视化图表创建成功")
return True
except Exception as e:
print(f"❌ {sensor_name} 可视化图表创建失败: {e}")
return False
def create_all_visualizations():
"""为所有传感器创建可视化"""
print("🎨 为所有传感器创建可视化...")
success_count = 0
for sensor_name in SENSOR_NAMES:
if create_single_sensor_visualization(sensor_name):
success_count += 1
print(f"📊 成功创建了 {success_count}/{len(SENSOR_NAMES)} 个可视化图表")
return success_count
def list_created_graphs():
"""列出创建的Action Graph"""
print("\n📋 创建的Action Graph列表:")
stage = omni.usd.get_context().get_stage()
for sensor_name in SENSOR_NAMES:
graph_path = f"/ActionGraph_{sensor_name}_Viz"
color = COLOR_CONFIG.get(sensor_name, [1.0, 0.0, 0.0, 1.0])
color_desc = f"RGB({color[0]:.1f}, {color[1]:.1f}, {color[2]:.1f})"
if stage.GetPrimAtPath(graph_path):
print(f" ✅ {sensor_name}: {graph_path} - {color_desc}")
else:
print(f" ❌ {sensor_name}: 图表未创建")
# ==================== 主要执行函数 ====================
async def main():
"""主要执行函数"""
try:
# 1. 启用必要扩展
enable_required_extensions()
# 等待扩展加载
await omni.kit.app.get_app().next_update_async()
# 2. 创建所有可视化
success_count = create_all_visualizations()
# 3. 列出创建结果
list_created_graphs()
if success_count > 0:
print(f"\n🎉 Action Graph创建完成!")
print("📋 颜色说明:")
print(" 🔴 红色系: 前方传感器")
print(" 🔵 蓝色系: 后方传感器")
print(" 🟢 绿色系: 左侧传感器")
print(" 🟡 黄色系: 右侧传感器")
print(" 🎨 深色: 底层传感器 | 浅色: 顶层传感器")
print("\n💡 使用说明:")
print("1. 点击'Play'按钮开始仿真")
print("2. 观察8条不同颜色的光束线条")
print("3. 在场景中添加物体测试光束碰撞")
print("4. 可在Window > Visual Scripting > Action Graph查看图表")
else:
print("❌ 没有成功创建任何可视化图表")
print("💡 请确保:")
print(" 1. 传感器已正确创建")
print(" 2. 机器人路径正确")
print(" 3. 必要扩展已启用")
except Exception as e:
print(f"❌ 执行失败: {e}")
import traceback
traceback.print_exc()
# 运行主函数
asyncio.ensure_future(main())
print("🚀 Action Graph可视化脚本开始执行...")
有些小bug,需要手动修改高度如下图
然后按左侧play键,显示如下图,没有添加关节,所以光线不会跟随机器人,是正常的
然后手动添加关节(避免父子关系错误)如下图
依次把8个传感器都链接如下图,注意ctrl先点baselink再点对应传感器,顺序影响父子关系

然后将下图文件夹移至baselink文件夹中
之后在script editor运行以下代码
js
import omni.usd
from pxr import UsdPhysics
def complete_sensor_cleanup():
"""完整清理传感器的物理属性和Joint"""
stage = omni.usd.get_context().get_stage()
sensor_names = [
"front_bottom", "back_bottom", "left_bottom", "right_bottom",
"front_top", "back_top", "left_top", "right_top"
]
base_path = "/World/create3_robot/create_3/base_link"
for sensor_name in sensor_names:
sensor_path = f"{base_path}/{sensor_name}"
sensor_prim = stage.GetPrimAtPath(sensor_path)
print(f"🔧 完整清理传感器: {sensor_name}")
if sensor_prim.IsValid():
# 1. 移除所有物理API
if sensor_prim.HasAPI(UsdPhysics.RigidBodyAPI):
sensor_prim.RemoveAPI(UsdPhysics.RigidBodyAPI)
print(f" ✅ 移除RigidBodyAPI")
if sensor_prim.HasAPI(UsdPhysics.CollisionAPI):
sensor_prim.RemoveAPI(UsdPhysics.CollisionAPI)
print(f" ✅ 移除CollisionAPI")
if sensor_prim.HasAPI(UsdPhysics.MassAPI):
sensor_prim.RemoveAPI(UsdPhysics.MassAPI)
print(f" ✅ 移除MassAPI")
# 2. 删除FixedJoint
joint_path = f"{sensor_path}/FixedJoint"
joint_prim = stage.GetPrimAtPath(joint_path)
if joint_prim.IsValid():
stage.RemovePrim(joint_path)
print(f" 🗑️ 删除FixedJoint")
# 3. 验证传感器状态
if sensor_prim.IsValid():
print(f" ✅ {sensor_name} 清理完成")
else:
print(f" ❌ {sensor_name} 不存在")
print("\n🎉 传感器完整清理完成!")
print("💡 现在传感器通过层级关系连接,无需Joint")
# 运行完整清理
complete_sensor_cleanup()
现在运行效果如下(笔者再次修改了高度后的效果)
然后也可以实时输出每个传感器方向测量的距离,在script editor运行下面代码
js
#!/usr/bin/env python3
"""
Isaac Sim 4.5 - LightBeam Sensor Distance Monitor (ASCII Only)
Monitor all sensor distances every 5 seconds - ASCII characters only
"""
import omni
from isaacsim.sensors.physx import _range_sensor
import time
import asyncio
import numpy as np
# ==================== Configuration ====================
ROBOT_PRIM_PATH = "/World/create3_robot"
# Sensor configuration (ASCII only)
SENSORS_CONFIG = [
{"name": "front_bottom", "layer": "Bottom", "direction": "Front", "symbol": "^"},
{"name": "back_bottom", "layer": "Bottom", "direction": "Back", "symbol": "v"},
{"name": "left_bottom", "layer": "Bottom", "direction": "Left", "symbol": "<"},
{"name": "right_bottom", "layer": "Bottom", "direction": "Right", "symbol": ">"},
{"name": "front_top", "layer": "Top", "direction": "Front", "symbol": "^"},
{"name": "back_top", "layer": "Top", "direction": "Back", "symbol": "v"},
{"name": "left_top", "layer": "Top", "direction": "Left", "symbol": "<"},
{"name": "right_top", "layer": "Top", "direction": "Right", "symbol": ">"},
]
print("Starting LightBeam Sensor Distance Monitor...")
class LightBeamMonitor:
def __init__(self):
self.lightbeam_interface = None
self.timeline = None
self.monitoring = False
self.last_output_time = 0
self.output_interval = 5.0 # 5 seconds
def initialize(self):
"""Initialize sensor interface"""
try:
self.lightbeam_interface = _range_sensor.acquire_lightbeam_sensor_interface()
self.timeline = omni.timeline.get_timeline_interface()
print("SUCCESS: Sensor interface initialized")
return True
except Exception as e:
print(f"ERROR: Sensor interface failed - {e}")
return False
def get_sensor_distance(self, sensor_path):
"""Get distance data from single sensor"""
try:
if not self.timeline.is_playing():
return None, 0, []
# Get sensor data
linear_depth = self.lightbeam_interface.get_linear_depth_data(sensor_path)
beam_hit = self.lightbeam_interface.get_beam_hit_data(sensor_path)
hit_pos = self.lightbeam_interface.get_hit_pos_data(sensor_path)
if linear_depth is not None and len(linear_depth) > 0:
valid_distances = []
min_distance = float('inf')
hit_count = 0
for i in range(len(linear_depth)):
if beam_hit[i]: # If beam hit
distance = linear_depth[i]
if distance > 0.1: # Filter invalid data
valid_distances.append(distance)
min_distance = min(min_distance, distance)
hit_count += 1
final_distance = min_distance if min_distance != float('inf') else None
return final_distance, hit_count, valid_distances
return None, 0, []
except Exception as e:
return None, 0, []
def get_distance_status(self, distance):
"""Get status based on distance"""
if distance is None:
return "NO_DETECT", "[X]", "----"
elif distance < 1.0:
return "VERY_CLOSE", "[!]", "CRIT"
elif distance < 2.0:
return "CLOSE", "[*]", "WARN"
elif distance < 4.0:
return "MEDIUM", "[-]", "NORM"
elif distance < 6.0:
return "FAR", "[+]", "SAFE"
else:
return "VERY_FAR", "[=]", "DIST"
def format_distance(self, distance):
"""Format distance display"""
if distance is None:
return "----m"
else:
return f"{distance:.2f}m"
def output_all_sensor_data(self):
"""Output all sensor data"""
if not self.timeline.is_playing():
print("PAUSE: Simulation not running, cannot get sensor data")
return
print("\n" + "="*90)
print(f"iRobot Create 3 - LightBeam Distance Monitor | {time.strftime('%H:%M:%S')}")
print("="*90)
# Group by layer
layers = {"Top": [], "Bottom": []}
for sensor_config in SENSORS_CONFIG:
sensor_name = sensor_config["name"]
# Updated sensor path - now under base_link
sensor_path = f"{ROBOT_PRIM_PATH}/create_3/base_link/{sensor_name}"
direction = sensor_config["direction"]
layer = sensor_config["layer"]
symbol = sensor_config["symbol"]
# Get distance data
distance, hit_count, all_distances = self.get_sensor_distance(sensor_path)
status_text, status_icon, status_code = self.get_distance_status(distance)
distance_text = self.format_distance(distance)
# Build display info
if hit_count > 1: # Multiple beams
avg_distance = np.mean(all_distances) if all_distances else None
avg_text = self.format_distance(avg_distance)
info = f" {symbol} {direction:>5} | {distance_text:>8} (min) | {avg_text:>8} (avg) | {hit_count}rays | {status_code} {status_icon}"
else:
info = f" {symbol} {direction:>5} | {distance_text:>8} | {hit_count}rays | {status_code} {status_icon}"
layers[layer].append(info)
# Output top layer sensors
print("TOP Layer Sensors (Z = +0.1m):")
for info in layers["Top"]:
print(info)
print("")
# Output bottom layer sensors
print("BOTTOM Layer Sensors (Z = -0.5m):")
for info in layers["Bottom"]:
print(info)
# Statistics
all_distances = []
total_hits = 0
active_sensors = 0
for sensor_config in SENSORS_CONFIG:
sensor_name = sensor_config["name"]
sensor_path = f"{ROBOT_PRIM_PATH}/create_3/base_link/{sensor_name}"
distance, hit_count, _ = self.get_sensor_distance(sensor_path)
if distance is not None:
all_distances.append(distance)
active_sensors += 1
total_hits += hit_count
if all_distances:
min_dist = min(all_distances)
max_dist = max(all_distances)
avg_dist = np.mean(all_distances)
print("")
print("STATISTICS:")
print(f" Closest: {min_dist:.2f}m | Farthest: {max_dist:.2f}m | Average: {avg_dist:.2f}m")
print(f" Total hits: {total_hits} | Active sensors: {active_sensors}/8")
# Safety assessment
if min_dist < 1.0:
safety = "DANGER - AVOID IMMEDIATELY"
safety_level = "CRITICAL"
elif min_dist < 2.0:
safety = "WARNING - BE CAREFUL"
safety_level = "WARNING"
elif min_dist < 4.0:
safety = "CAUTION - KEEP WATCHING"
safety_level = "CAUTION"
else:
safety = "SAFE - NORMAL OPERATION"
safety_level = "NORMAL"
print(f" Safety Status: {safety} ({safety_level})")
# Direction analysis
direction_analysis = self.analyze_directions(all_distances)
if direction_analysis:
print(f" Direction Advice: {direction_analysis}")
else:
print("")
print("STATISTICS: No obstacles detected")
print(" Safety Status: SAFE - NO OBSTACLES")
print("="*90)
def analyze_directions(self, distances):
"""Analyze safety in different directions"""
if not distances:
return None
min_dist = min(distances)
if min_dist > 4.0:
return "Open space - free movement"
elif min_dist > 2.0:
return "Reduce speed - proceed carefully"
else:
return "STOP or retreat to safe distance"
def start_monitoring(self):
"""Start monitoring"""
if not self.initialize():
return
self.monitoring = True
print("SUCCESS: Monitoring started - Output every 5 seconds")
print("INFO: Make sure to click 'Play' button to start simulation")
print("INFO: Press Ctrl+C to stop monitoring")
print("INFO: Sensor paths updated for cleaned hierarchy structure\n")
# Output immediately
self.output_all_sensor_data()
self.last_output_time = time.time()
def update(self):
"""Update monitoring - call in main loop"""
if not self.monitoring:
return
current_time = time.time()
if current_time - self.last_output_time >= self.output_interval:
self.output_all_sensor_data()
self.last_output_time = current_time
def stop_monitoring(self):
"""Stop monitoring"""
self.monitoring = False
print("\nSTOP: Monitoring stopped")
def set_output_interval(self, seconds):
"""Set output interval"""
self.output_interval = seconds
print(f"INFO: Output interval set to {seconds} seconds")
# ==================== Global monitor instance ====================
monitor = LightBeamMonitor()
# ==================== Main execution function ====================
async def main():
"""Main execution function"""
try:
# Start monitoring
monitor.start_monitoring()
# Keep running monitoring
while monitor.monitoring:
monitor.update()
await asyncio.sleep(0.1) # Avoid high CPU usage
except KeyboardInterrupt:
print("\nINFO: Stop signal received...")
monitor.stop_monitoring()
except Exception as e:
print(f"ERROR: Monitoring error - {e}")
monitor.stop_monitoring()
def start_monitoring():
"""Convenient function to start monitoring"""
asyncio.ensure_future(main())
def stop_monitoring():
"""Convenient function to stop monitoring"""
monitor.stop_monitoring()
def set_interval(seconds):
"""Convenient function to set monitoring interval"""
monitor.set_output_interval(seconds)
# Auto start monitoring
start_monitoring()
print("READY: Distance monitoring script started!")
print("INFO: Available commands:")
print(" - stop_monitoring(): Stop monitoring")
print(" - set_interval(seconds): Set output interval")
print(" - start_monitoring(): Restart monitoring")
js
stop_monitoring() #如果需要停止监控,在Script Editor中运行:
笔者添加了一个物体测试输出距离(记得开启物理属性)
不想显示光线将下面几个文件deactivate即可
最后可以调整文件布局为下图baocun
