目录
描述:鼠标左键点击物体,将物体拾起,松开鼠标左键,物体跟随鼠标光标移动。再次点击鼠标左键,物体不在跟随鼠标,处于静止状态。
实现方法:射线。
1657678042844
写在前面:什么是射线?
简单来说就是当鼠标点击某个物体时,通过摄像机camera发射射线,射线与物体碰撞在一个点上。我们通过这个点找到该点对应的物体,先判断该物体是否是我们想要移动的(是否为可以移动的)。
如果是,那我们就拿到要操作的对象了,接下来就是让其坐标位置和鼠标位置保持一致即可。
具体解释和详细使用方法读者可自行查阅相关文献。
由此我们可以得出,我们要先声明一个射线的变量,还有碰撞点,由于有碰撞点,我们就必需为物体添加刚体组件。为了判断是不是我们要的物体,就定义一个布尔值。此外,为了区分鼠标点击这一动作是拾起还是放下物体,我们要声明一个标志量flag。为了得到该碰撞点对应的物体,我们要声明一个GameObject组件来得到它。
private Ray ra;//声明射线
private RaycastHit hit;//声明碰撞点
private bool is_element =false;//判断是否是我们要的物体
private int flag = 0;//标志量
private GameObject Element;//控件
接下来就是干正事儿了。
判断鼠标是否按下:
if (Input.GetMouseButtonDown(0))
{
}
鼠标按下后,摄像机往按下位置发射射线。
ra = Camera.main.ScreenPointToRay(Input.mousePosition);
判断射线是否跟物体发生碰撞得到碰撞点hit,并且同时判断该点对应的物体是不是我们要的。
判断物体是不是我们要的,这里我使用的是判断其标签是不是'element',因此应该给先给物体添加一个标签。
以上检测完后将布尔值设为true,并将碰撞点对应的物体给Element。
if (Physics.Raycast(ra, out hit)&&hit.collider.tag=="element")
{
is_element = true;
Element = hit.collider.gameObject;
}
判断鼠标按下是拾起还是放下。
这里我规定,鼠标拾起物体时,flag=1,再次点击flag=0。
总的判断部分代码为:
if (Input.GetMouseButtonDown(0))
{
ra = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ra, out hit)&&hit.collider.tag=="element")
{
is_element = true;
Element = hit.collider.gameObject;
Debug.Log(Element.transform.position);
if (flag == 0)
{
flag = 1;
}
else
{
flag = 0;
}
}
}
改变物体位置和鼠标位置一致。
我们要先得到鼠标的位置。
鼠标只有x和y轴,为了和物体位置一致,这里将鼠标的z轴设置为物体的坐标。
Vector3 mousePos = new Vector3(Input.mousePosition.x, Input.mousePosition.y,
Element.transform.position.z);
由于鼠标位置是屏幕坐标,而物体坐标是世界坐标,那我们就要把鼠标的屏幕坐标换成世界坐标。
Vector3 mouseSToW = Camera.main.ScreenToWorldPoint(mousePos);
细心的人可以发现,这里有个“陷阱”。
我们在把鼠标的二位坐标用三位坐标表示时,其z轴就是物体的世界坐标的位置,然后我们之后又把它当作屏幕坐标转化成世界坐标,那么最后的坐标肯定和以前的不一样了。
所以我们要先将物体的世界坐标转化成成屏幕坐标,在把屏幕坐标的z轴坐标给鼠标的屏幕坐标,然后一同转化成世界坐标。然后将得到的世界坐标给物体。
Vector3 targetScreenPos = Camera.main.WorldToScreenPoint(Element.transform.position);
Vector3 mousePos = new Vector3(Input.mousePosition.x, Input.mousePosition.y,targetScreenPos.z);
Element.transform.position = Camera.main.ScreenToWorldPoint(mousePos);
当flag=1时,我们是拾起物体的,因此在flag变为0之前,我们的物体都是跟着鼠标移动的。
因此以上操作都是在flag==1以及is_element=true的条件下进行的。
if (flag == 1&&is_element)
{
Vector3 targetScreenPos = Camera.main.WorldToScreenPoint(Element.transform.position);
Vector3 mousePos = new Vector3(Input.mousePosition.x, Input.mousePosition.y,targetScreenPos.z);
Element.transform.position = Camera.main.ScreenToWorldPoint(mousePos);
}
代码汇总得:
using System.Collections;
using System.Collections.Generic;
using System.Linq.Expressions;
using Unity.VisualScripting;
using UnityEngine;
public class camera : MonoBehaviour {
//public Camera ca;
private Ray ra;
private RaycastHit hit;
private bool is_element =false;
private int flag = 0;
private GameObject Element;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
if (Input.GetMouseButtonDown(0))
{
ra = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ra, out hit)&&hit.collider.tag=="element")
{
is_element = true;
Element = hit.collider.gameObject;
if (flag == 0)
{
flag = 1;
}
else
{
flag = 0;
}
}
}
if (flag == 1&&is_element)
{
Vector3 targetScreenPos = Camera.main.WorldToScreenPoint(Element.transform.position);
Vector3 mousePos = new Vector3(Input.mousePosition.x, Input.mousePosition.y,
targetScreenPos.z);
Element.transform.position = Camera.main.ScreenToWorldPoint(mousePos);
}
}
}
描述:长按鼠标左键,物体跟随鼠标移动,松开鼠标左键,物体停止运动。
实现方法:协程或者射线。
有了前面的坐标转换基础,再加上对协程的基本了解,这个实现是非常容易的,我就直接上代码吧。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Cooperation : MonoBehaviour
{
IEnumerator OnMouseDown() //使用协程
{
Vector3 targetScreenPos = Camera.main.WorldToScreenPoint(transform.position);//三维物体坐标转屏幕坐标
//将鼠标屏幕坐标转为三维坐标,再计算物体位置与鼠标之间的距离
var offset = transform.position - Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, targetScreenPos.z));
while (Input.GetMouseButton(0))
{
//将鼠标位置二维坐标转为三维坐标
Vector3 mousePos = new Vector3(Input.mousePosition.x, Input.mousePosition.y, targetScreenPos.z);
//将鼠标转换的三维坐标再转换成世界坐标+物体与鼠标位置的偏移量
var targetPos = Camera.main.ScreenToWorldPoint(mousePos) + offset;
transform.position = targetPos;
yield return new WaitForFixedUpdate();//循环执行
}
}
}
}
使用射线的方法与之类似,这里就不在赘述。
描述:类似于英雄联盟的移动方式,鼠标点击平面任意位置,物体立即朝该方向移动。
1657681859641
首先,对移动物体和地面进行bake,操作如下:
选中Cube,点击window—>AI—>Navigation

然后将Navigation Static勾选上

之后选择bake,地面和移动物体(Cube)都要勾选上。

代码我就直接给了,比较容易理解。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
public class Nvgt : MonoBehaviour
{
private NavMeshAgent navMeshAgent;
void Start()
{
navMeshAgent = gameObject.GetComponent<NavMeshAgent>();//初始化navMeshAgent
}
void Update()
{
if (Input.GetMouseButtonDown(0))//鼠标左键点下
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);//住摄像机向鼠标位置发射射线
RaycastHit hit;
if (Physics.Raycast(ray, out hit))//射线检验
{
if (hit.collider.gameObject.tag == "Plane")
{
navMeshAgent.SetDestination(hit.point);//mHit.point就是射线和plane的相交点,实为碰撞点
}
}
}
}
}
我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div
总的来说,我对ruby还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用
类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc
我正在尝试设置一个puppet节点,但rubygems似乎不正常。如果我通过它自己的二进制文件(/usr/lib/ruby/gems/1.8/gems/facter-1.5.8/bin/facter)在cli上运行facter,它工作正常,但如果我通过由rubygems(/usr/bin/facter)安装的二进制文件,它抛出:/usr/lib/ruby/1.8/facter/uptime.rb:11:undefinedmethod`get_uptime'forFacter::Util::Uptime:Module(NoMethodError)from/usr/lib/ruby
我想了解Ruby方法methods()是如何工作的。我尝试使用“ruby方法”在Google上搜索,但这不是我需要的。我也看过ruby-doc.org,但我没有找到这种方法。你能详细解释一下它是如何工作的或者给我一个链接吗?更新我用methods()方法做了实验,得到了这样的结果:'labrat'代码classFirstdeffirst_instance_mymethodenddefself.first_class_mymethodendendclassSecond使用类#returnsavailablemethodslistforclassandancestorsputsSeco
我在我的项目中添加了一个系统来重置用户密码并通过电子邮件将密码发送给他,以防他忘记密码。昨天它运行良好(当我实现它时)。当我今天尝试启动服务器时,出现以下错误。=>BootingWEBrick=>Rails3.2.1applicationstartingindevelopmentonhttp://0.0.0.0:3000=>Callwith-dtodetach=>Ctrl-CtoshutdownserverExiting/Users/vinayshenoy/.rvm/gems/ruby-1.9.3-p0/gems/actionmailer-3.2.1/lib/action_mailer
设置:狂欢ruby1.9.2高线(1.6.13)描述:我已经相当习惯在其他一些项目中使用highline,但已经有几个月没有使用它了。现在,在Ruby1.9.2上全新安装时,它似乎不允许在同一行回答提示。所以以前我会看到类似的东西:require"highline/import"ask"Whatisyourfavoritecolor?"并得到:Whatisyourfavoritecolor?|现在我看到类似的东西:Whatisyourfavoritecolor?|竖线(|)符号是我的终端光标。知道为什么会发生这种变化吗? 最佳答案
我已经从我的命令行中获得了一切,所以我可以运行rubymyfile并且它可以正常工作。但是当我尝试从sublime中运行它时,我得到了undefinedmethod`require_relative'formain:Object有人知道我的sublime设置中缺少什么吗?我正在使用OSX并安装了rvm。 最佳答案 或者,您可以只使用“require”,它应该可以正常工作。我认为“require_relative”仅适用于ruby1.9+ 关于ruby-主要:Objectwhenrun
我有一个具有一些属性的模型:attr1、attr2和attr3。我需要在不执行回调和验证的情况下更新此属性。我找到了update_column方法,但我想同时更新三个属性。我需要这样的东西:update_columns({attr1:val1,attr2:val2,attr3:val3})代替update_column(attr1,val1)update_column(attr2,val2)update_column(attr3,val3) 最佳答案 您可以使用update_columns(attr1:val1,attr2:val2
我不确定传递给方法的对象的类型是否正确。我可能会将一个字符串传递给一个只能处理整数的函数。某种运行时保证怎么样?我看不到比以下更好的选择:defsomeFixNumMangler(input)raise"wrongtype:integerrequired"unlessinput.class==FixNumother_stuffend有更好的选择吗? 最佳答案 使用Kernel#Integer在使用之前转换输入的方法。当无法以任何合理的方式将输入转换为整数时,它将引发ArgumentError。defmy_method(number)