2017-02-28 17:23:39 xuanjian6 阅读数 929
  • Unity3D入门到精通-(3)Unity资源管理精讲

    本次系列课程的目标是让Unity3D初学者掌握Unity3d的资源管理技术进行了全面介绍,特别对AssetBundle资源如何进行更新,以及加载(依赖资源加载)进行了系统的介绍。 适合对象:Unity初学开发者,Unity中级开发者,网络程序开发者,所有对游戏开发有兴趣的人员。 学习条件:有一定的Unity3D基础,了解C#的基本开发知识。

    4729 人正在学习 去看看 张刚
 void OnMouseDrag()
    {
        //屏幕空间拖拽
        //float distance_to_screen = Camera.main.WorldToScreenPoint(gameObject.transform.position).z;
        //transform.position = Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, distance_to_screen));


        //float distance_to_screen = Camera.main.WorldToScreenPoint(gameObject.transform.position).z;
        //Vector3 pos_move = Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, distance_to_screen));
        //transform.position = new Vector3(pos_move.x, transform.position.y, pos_move.z);

        ///立体空间拖拽
        // Bit shift the index of the layer (8) to get a bit mask
        int layerMask = 1 << 9;

        // This would cast rays only against colliders in layer 8.
        // But instead we want to collide against everything except layer 8. The ~ operator does this, it inverts a bitmask.
        layerMask = ~layerMask;

        RaycastHit hit;
        Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
        if (Physics.Raycast(ray, out hit, Mathf.Infinity, layerMask))
        {
            transform.position = new Vector3(hit.point.x, transform.position.y, hit.point.z);
        }
    }

2016-04-26 15:23:16 a2587539515 阅读数 2503
  • Unity3D入门到精通-(3)Unity资源管理精讲

    本次系列课程的目标是让Unity3D初学者掌握Unity3d的资源管理技术进行了全面介绍,特别对AssetBundle资源如何进行更新,以及加载(依赖资源加载)进行了系统的介绍。 适合对象:Unity初学开发者,Unity中级开发者,网络程序开发者,所有对游戏开发有兴趣的人员。 学习条件:有一定的Unity3D基础,了解C#的基本开发知识。

    4729 人正在学习 去看看 张刚

官方的demo(http://unity3d.com/cn/showcase/live-demos#shadows)中的Room of Shadows,一开始抱着学习室内灯光效果的想法去看的,后来发现这个demo中有一个拖拽物体的脚本,正好最近玩了好多游戏都是这样的,好奇心来了,学习下原理,看了之后发现原理蛮简单的,单纯使用SpringJoint即可实现,这里把脚本的代码沾上了来,做个记录。(这个脚本中不止是拖拽,还有高光,基于重绘Mesh的,一并记了)

DragRigdbodyShadow.js

var spring = 50.0;
var damper = 5.0;
var drag = 10.0;
var angularDrag = 5.0;
var distance = 0.2;
var pushForce = 0.2;
var attachToCenterOfMass = false;

var highlightMaterial : Material;
private var highlightObject : GameObject;

private var springJoint : SpringJoint;

function Update()
{
	var mainCamera = FindCamera();
	
	highlightObject = null;
	if( springJoint != null && springJoint.connectedBody != null )
	{
		highlightObject = springJoint.connectedBody.gameObject;
	}
	else
	{
		// We need to actually hit an object
		var hitt : RaycastHit;
		if( Physics.Raycast(mainCamera.ScreenPointToRay(Input.mousePosition),  hitt, 100 ) ) {
			if( hitt.rigidbody && !hitt.rigidbody.isKinematic ) {
			    highlightObject = hitt.rigidbody.gameObject;
			    //这里通过射线判断选中物体,加入highlightObject中,之后通过OnPostRender函数重绘
			}
		}
	}
	
		
	// Make sure the user pressed the mouse down
	if (!Input.GetMouseButtonDown (0))
		return;

		
	// We need to actually hit an object
	var hit : RaycastHit;
	if (!Physics.Raycast(mainCamera.ScreenPointToRay(Input.mousePosition),  hit, 100)) {
		return;
	}
	// We need to hit a rigidbody that is not kinematic
	if (!hit.rigidbody || hit.rigidbody.isKinematic) {
		return;
	}
	
	if (!springJoint)
	{
		var go = new GameObject("Rigidbody dragger");
		body = go.AddComponent.<Rigidbody>();
		springJoint = go.AddComponent.<SpringJoint>();
		body.isKinematic = true;
	    //建立一个SpringJoint(反弹关节),弹簧,来模拟力
	}
	
	springJoint.transform.position = hit.point;
	if (attachToCenterOfMass)
	{
		var anchor = transform.TransformDirection(hit.rigidbody.centerOfMass) + hit.rigidbody.transform.position;
		anchor = springJoint.transform.InverseTransformPoint(anchor);
		springJoint.anchor = anchor;
	}
	else
	{
	    springJoint.anchor = Vector3.zero;
	}
	//这里判断是否强制连接物体重心,是的话将锚点置为重心
	springJoint.spring = spring;
	springJoint.damper = damper;
	springJoint.maxDistance = distance;
	springJoint.connectedBody = hit.rigidbody;
	
	
	DragObject(hit.distance, hit.point, mainCamera.ScreenPointToRay(Input.mousePosition).direction);
    
}

function DragObject (distance : float, hitpoint : Vector3, dir : Vector3)
{
	var startTime = Time.time;
	var mousePos = Input.mousePosition;
	
	
	var oldDrag = springJoint.connectedBody.drag;
	var oldAngularDrag = springJoint.connectedBody.angularDrag;
	springJoint.connectedBody.drag = drag;
	springJoint.connectedBody.angularDrag = angularDrag;
	var mainCamera = FindCamera();
	while (Input.GetMouseButton (0))
	{
		var ray = mainCamera.ScreenPointToRay (Input.mousePosition);
		springJoint.transform.position = ray.GetPoint(distance);
		yield;
	}
    //这个地方就是拖动弹簧,拉动物体,这个拉动很有意思,这里用的是distance,这样的话拉动的范围是以摄像机为圆心,以点击时记录下来的distance为半径的球,效果还不错,有立体拉动的感觉
	if (Mathf.Abs(mousePos.x - Input.mousePosition.x) <= 2 && Mathf.Abs(mousePos.y - Input.mousePosition.y) <= 2 && Time.time - startTime < .2 && springJoint.connectedBody)
	{
		dir.y = 0;
		dir.Normalize();
		springJoint.connectedBody.AddForceAtPosition(dir * pushForce, hitpoint, ForceMode.VelocityChange);
		ToggleLight( springJoint.connectedBody.gameObject );
	}	
	//这个的作用是点击的时候,做出一个拍打物体的感觉
	
	if (springJoint.connectedBody)
	{
		springJoint.connectedBody.drag = oldDrag;
		springJoint.connectedBody.angularDrag = oldAngularDrag;
		springJoint.connectedBody = null;
	}
}

static function ToggleLight( go : GameObject )
    {	
	var theLight : Light = go.GetComponentInChildren(Light);
	if( !theLight )
		return;
		
	theLight.enabled = !theLight.enabled;
	var illumOn = theLight.enabled;
	var renderers = go.GetComponentsInChildren(MeshRenderer);
	for( var r : MeshRenderer in renderers )
	{
		if( r.gameObject.layer == 1 )
		{
			r.material.shader = Shader.Find(illumOn ? "Self-Illumin/Diffuse" : "Diffuse");
		}
}
//开关灯,场景互动
}

function FindCamera ()
{
	if (GetComponent.<Camera>())
		return GetComponent.<Camera>();
	else
		return Camera.main;
}

function OnPostRender()
{
	if( highlightObject == null )
		return;
		
	var go = highlightObject;
	highlightMaterial.SetPass( 0 );
	var meshes = go.GetComponentsInChildren(MeshFilter);
	for( var m : MeshFilter in meshes )
	{
		Graphics.DrawMeshNow( m.sharedMesh, m.transform.position, m.transform.rotation );
	}
///setPass就是设置通道,走的是Shader中的第一个通道,下面的将网格重新绘制一次,做到高光效果,从实现上看,绘制的时候实用的就是上面的高光贴图
}


Highlight.shader
Shader "Shadows/Drag Highlight" {
Properties {
	_Color ("Main Color", Color) = (1,1,1,1)
}
SubShader {
	Pass {
		ZWrite Off
		Offset -1, -1
		Blend SrcAlpha OneMinusSrcAlpha
		Color [_Color]
	}
} 
}

这里的Blend是一个自身颜色和其他颜色的混合,在设置透明度时候用,这里使用它来设置重绘网格的透明度,表现为高光强度

具体见http://blog.sina.com.cn/s/blog_471132920101d8z5.html

2018-06-12 14:57:13 q764424567 阅读数 3248
  • Unity3D入门到精通-(3)Unity资源管理精讲

    本次系列课程的目标是让Unity3D初学者掌握Unity3d的资源管理技术进行了全面介绍,特别对AssetBundle资源如何进行更新,以及加载(依赖资源加载)进行了系统的介绍。 适合对象:Unity初学开发者,Unity中级开发者,网络程序开发者,所有对游戏开发有兴趣的人员。 学习条件:有一定的Unity3D基础,了解C#的基本开发知识。

    4729 人正在学习 去看看 张刚

手指拖动物体,也是交互中比较常见的一种操作,那么就让我们来看看怎么实现吧


首先看看实现效果吧

这里写图片描述

接下来说一下实现步骤
1. 新建一个Cube,设置好物体的坐标大小
2. 新建脚本Drag.cs,叫脚本Drag.cs挂在Cube上
3. 编写脚本Drag.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Drag : MonoBehaviour
{
    //偏移值
    Vector3 m_Offset;
    //当前物体对应的屏幕坐标
    Vector3 m_TargetScreenVec;

    private IEnumerator OnMouseDown()
    {
        //当前物体对应的屏幕坐标
        m_TargetScreenVec = Camera.main.WorldToScreenPoint(transform.position);
        //偏移值=物体的世界坐标,减去转化之后的鼠标世界坐标(z轴的值为物体屏幕坐标的z值)
        m_Offset = transform.position - Camera.main.ScreenToWorldPoint(new Vector3
        (Input.mousePosition.x, Input.mousePosition.y, m_TargetScreenVec.z));
        //当鼠标左键点击
        while (Input.GetMouseButton(0))
        {
            //当前坐标等于转化鼠标为世界坐标(z轴的值为物体屏幕坐标的z值)+ 偏移量
            transform.position = Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x,
             Input.mousePosition.y, m_TargetScreenVec.z)) + m_Offset;
            //等待固定更新
            yield return new WaitForFixedUpdate();
        }
    }
}
2019-08-11 22:05:36 piai9568 阅读数 59
  • Unity3D入门到精通-(3)Unity资源管理精讲

    本次系列课程的目标是让Unity3D初学者掌握Unity3d的资源管理技术进行了全面介绍,特别对AssetBundle资源如何进行更新,以及加载(依赖资源加载)进行了系统的介绍。 适合对象:Unity初学开发者,Unity中级开发者,网络程序开发者,所有对游戏开发有兴趣的人员。 学习条件:有一定的Unity3D基础,了解C#的基本开发知识。

    4729 人正在学习 去看看 张刚

Kapture 2019-08-10 at 21.45.22.gif

游戏中,有时需要一个指示条来标明拖拽的力度。比如愤怒的小鸟 拖弹弓的力度,或者高尔夫游戏里挥杆的力度等等。
今天我们使用LineRenderer来实现下上面效果图中的效果。

首先在Update中侦听鼠标按下,移动,和松开三个时间

 if (Input.GetMouseButtonDown(0))
        {
           
        }
        if (Input.GetMouseButton(0))
        {
           
        }
        if (Input.GetMouseButtonUp(0))
        {
            
        }

我们这来的LineRenderer只需要两个点。设置LineRenderer的positionCount为2。
将鼠标按下时的坐标设置为起点,将鼠表按下后移动的当前位置设置为LineRender的第二个点。

鼠标按下世界坐标位置,我们可以通过 Camera.ScreenToWorldPoint来实现,默认出来的位置距离相机的Z值为0,所以上一个camOffset = new Vector3(0,0,10)。

startPos = camera.ScreenToWorldPoint(Input.mousePosition) + camOffset;

同时在Inspector中 添加一个 曲线来控制 线条的宽度,我们可以设置起点处宽一点,第二个顶点处窄一点。

 [SerializeField] AnimationCurve ac;

屏幕快照 2019-08-10 下午10.14.04.png

通过LineRenderer.numCapVertices = 10;将线条的两端设置为圆角。

完整代码如下:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class DragIndicatorScript : MonoBehaviour
{

    Vector3 startPos;
    Vector3 endPos;
    Camera camera;
    LineRenderer lr;

    Vector3 camOffset = new Vector3(0, 0, 10);

    [SerializeField] AnimationCurve ac;

    // Start is called before the first frame update
    void Start()
    {
        camera = Camera.main;
    }

    // Update is called once per frame
    void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            if (lr == null)
            {
                lr = gameObject.AddComponent<LineRenderer>();
            }
            lr.enabled = true;
            lr.positionCount = 2;
            startPos = camera.ScreenToWorldPoint(Input.mousePosition) + camOffset;
            lr.SetPosition(0, startPos);
            lr.useWorldSpace = true;
            lr.widthCurve = ac;
            lr.numCapVertices = 10;
        }
        if (Input.GetMouseButton(0))
        {
            endPos = camera.ScreenToWorldPoint(Input.mousePosition) + camOffset;
            lr.SetPosition(1, endPos);
        }
        if (Input.GetMouseButtonUp(0))
        {
            lr.enabled = false;
        }
    }
}

更多Unity相关教程,关注微信公众号UnityAsk。

2015-09-22 17:52:38 u012842807 阅读数 2980
  • Unity3D入门到精通-(3)Unity资源管理精讲

    本次系列课程的目标是让Unity3D初学者掌握Unity3d的资源管理技术进行了全面介绍,特别对AssetBundle资源如何进行更新,以及加载(依赖资源加载)进行了系统的介绍。 适合对象:Unity初学开发者,Unity中级开发者,网络程序开发者,所有对游戏开发有兴趣的人员。 学习条件:有一定的Unity3D基础,了解C#的基本开发知识。

    4729 人正在学习 去看看 张刚
using System.Collections;
using UnityEngine;
public class MoveMouse : MonoBehaviour
{
    //下面的函数是当鼠标触碰到碰撞体或者刚体时调用,我的碰撞体设置是mesh collider,然后别忘了,给这个collider添加物理材质
    //值得注意的是世界坐标系转化为屏幕坐标系,Z轴是不变的
    IEnumerator OnMouseDown()
    {
        //将物体由世界坐标系转化为屏幕坐标系 ,由vector3 结构体变量ScreenSpace存储,以用来明确屏幕坐标系Z轴的位置
        Vector3 ScreenSpace = Camera.main.WorldToScreenPoint(transform.position);
        //完成了两个步骤,1由于鼠标的坐标系是2维的,需要转化成3维的世界坐标系,2只有三维的情况下才能来计算鼠标位置与物体的距离,offset即是距离
        Vector3 offset = transform.position - Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, ScreenSpace.z));
        Debug.Log("down");
        //当鼠标左键按下时
        while (Input.GetMouseButton(0))
        {
            //得到现在鼠标的2维坐标系位置
            Vector3 curScreenSpace = new Vector3(Input.mousePosition.x, Input.mousePosition.y, ScreenSpace.z);
            //将当前鼠标的2维位置转化成三维的位置,再加上鼠标的移动量
            Vector3 CurPosition = Camera.main.ScreenToWorldPoint(curScreenSpace) + offset;
            //CurPosition就是物体应该的移动向量赋给transform的position属性
            transform.position = CurPosition;
            //这个很主要
            yield return new WaitForFixedUpdate();
        }
    }
}
没有更多推荐了,返回首页