如何实现将游戏对象传送到玩家点击的屏幕位置?
游戏对象点击屏幕传送的实现方法
下面分主流游戏引擎给你讲具体实现方式,核心思路都是检测屏幕点击→转换屏幕坐标到世界坐标→将目标对象移动到该坐标,不同引擎的API略有差异:
Unity(C#)
- 给要处理逻辑的GameObject挂一个脚本,比如
TeleportOnClick - 在脚本里绑定要传送的对象和主相机,然后在Update里检测鼠标点击:
using UnityEngine; public class TeleportOnClick : MonoBehaviour { public GameObject objectToTeleport; // 拖拽要传送的对象到这里 public Camera mainCamera; // 拖拽主相机到这里,默认也可以用Camera.main void Update() { // 检测左键按下 if (Input.GetMouseButtonDown(0)) { // 从相机发射射线到点击位置 Ray ray = mainCamera.ScreenPointToRay(Input.mousePosition); if (Physics.Raycast(ray, out RaycastHit hitInfo)) { // 把对象移到射线击中的位置(比如地面) objectToTeleport.transform.position = hitInfo.point; } } } }
注意:
- 要确保地面或你想点击的平面有
Collider组件,射线才能检测到 - 如果是2D游戏,把
Physics.Raycast换成Physics2D.Raycast,用2D碰撞体
Unreal Engine(C++/蓝图)
蓝图实现
- 打开PlayerController的蓝图,在
BeginPlay里绑定鼠标左键输入到自定义事件 - 自定义事件里做以下操作:
- 用
Deproject Screen to World把屏幕坐标转成世界射线 - 用
Line Trace By Channel做射线检测,获取击中位置 - 调用
Set Actor Location把目标对象移到该位置
- 用
C++实现
#include "CoreMinimal.h" #include "GameFramework/PlayerController.h" #include "TeleportController.generated.h" UCLASS() class YOURPROJECT_API ATeleportController : public APlayerController { GENERATED_BODY() protected: virtual void BeginPlay() override; private: UFUNCTION() void OnLeftClick(); UPROPERTY(EditAnywhere, Category = "Teleport") AActor* TargetObject; // 在Details面板选要传送的对象 };
#include "TeleportController.h" #include "Kismet/GameplayStatics.h" void ATeleportController::BeginPlay() { Super::BeginPlay(); // 绑定鼠标左键输入(要先在Project Settings的Input里加LeftMouseButton映射) InputComponent->BindAction("LeftMouseButton", IE_Pressed, this, &ATeleportController::OnLeftClick); } void ATeleportController::OnLeftClick() { FVector2D MousePos; if (GetMousePosition(MousePos.X, MousePos.Y)) { FVector WorldLoc, WorldDir; DeprojectScreenPositionToWorld(MousePos.X, MousePos.Y, WorldLoc, WorldDir); FHitResult Hit; // 射线检测,长度1000单位,可按需调整 GetWorld()->LineTraceSingleByChannel(Hit, WorldLoc, WorldLoc + WorldDir * 1000, ECC_Visibility); if (Hit.bBlockingHit && TargetObject) { TargetObject->SetActorLocation(Hit.Location); } } }
Godot(GDScript)
3D场景
extends Node3D @onready var teleport_target = $TeleportTarget # 引用要传送的对象 @onready var main_camera = $Camera3D func _input(event): # 检测左键点击 if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT and event.pressed: # 获取射线的起点和方向 var ray_origin = main_camera.project_ray_origin(event.position) var ray_dir = main_camera.project_ray_normal(event.position) # 射线检测,检测范围1000单位 var space_state = get_world_3d().direct_space_state var hit_result = space_state.intersect_ray(Ray3D(ray_origin, ray_dir * 1000)) if hit_result: # 移动对象到击中位置 teleport_target.global_position = hit_result.position
2D场景(更简单)
extends Node2D @onready var teleport_target = $TeleportTarget func _input(event): if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT and event.pressed: # 直接获取鼠标全局位置,赋值给对象 teleport_target.global_position = get_global_mouse_position()
通用注意点:
- 如果不需要检测地面,只是传送到点击的屏幕对应的世界坐标(比如空中),可以跳过射线检测,直接用坐标转换后的位置
- 可以给传送加个动画或者粒子效果,提升体验
内容的提问来源于stack exchange,提问作者pokefalle
相关产品推荐
相关产品推荐

