Unity3D入门篇
Posted Shawn的代码日常
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Unity3D入门篇相关的知识,希望对你有一定的参考价值。
相关网址汇总
文章目录
1.Unity官网(外网):https://unity.com
2.Unity官网(内网):https://unity.cn
3.Unity学习:
https://learn.unity.com
https://learn.unity.com/projects
4.Unity官方商店:https://assetstore.unity.com
基本操作以及模块简介
视角操作以及组件
组件设置
1.导航器Gizmo
:表示世界坐标的方向
2.栅格Grid
:表示XZ坐标平面
3.天空盒Skybox
:表示游戏世界的背景
3D视图:
1.旋转视图
:右键 / Alt+左键
2.视角缩放
:滚轮 / Alt+右键
导航器:
1.按住Shift,点击中间的小方块,恢复方向
2.点Y轴,顶视图
3.点X轴,右视图
4.点Z轴,前视图
视野中心:
1.将某物体放置于世界中心
:选中一个物体,长按住F键
此时旋转视图,似是绕着物体旋转。
2.出生点:添加一个新物体,其位于视图中心。并不是(0,0,0)。
透视和正交:
透视视图Perspective
:近大远小
正交视图Orthographic
:等距视图Isometric,物体显示与距离无关
在导航器下方的persp处调节。
透视,广角设定
:
摄像机的广角Field默认为60°。广角越大,透视畸变太厉害。可以设为30~40°。
物体操作
Unity自带的基础模型
- Cube,立方体
- Sphere,球体
- Capsule,胶囊体
- Cylinder,圆柱体
- Plane,平面
旋转工具Rotate Tools:
在Unity中,顺时针旋转,对应方向参量为负方向。
逆时针旋转,对应方向参量为正方形。
此外,按住ctrl键旋转使其每次角增量为15°。
缩放工具Scale Tools:
*AF扩展插件:AfSimpleExtension
扩展功能:
1.输出物体的尺寸Scale
2.聚焦到事业重心 G键
3.快速切换正交视图与等距视图。
模型操作
网格Mesh:存储了模型的形状数据(面,顶点坐标,法向坐标等)。
材质Material:需添加到物体上,定义了物体的表面细节(颜色,是否金属,粗糙程度,是否透明…)
纹理Textures:需添加到材质上,可以是贴图。
模型建好以后一般导出为 fbx
文件格式。
在Unity中,
- 一个平面是没有厚度的
- 正面可见,背面透明
或者说,平面的背面不会被渲染。
※ FBX文件的使用方式:
1.材质替换
- 选中 *.fbx 文件
- 在Inspector 中切到 Materials属性—>Use Embeded Materials,On Demand Remap:映射新的材质
- 点Apply 应用
2.使用外部材质 Use External Materials - 选中fbx文件
- Location:Use External Materials使用外部材质
- 点Apply应用,将内嵌材质解压缩到Materials目录下
- 直接修改Materials目录下的材质文件。
资源文件
资源文件:Assets目录下的文件,被称为资源。
常见类型:
- 模型文件Model
*.fbx
- 图片文件Texture
*.jpg/png/psd/tif
- 音频文件AudioClip
*.mp3/wav/aiff
- 脚本文件Script
*.cs
- 材质文件,场景文件
*.mat,*.unity
轴心,父子关系,空物体
Global全局坐标系:绝对坐标,其X Y Z 指向世界的上下东西南北
Local本地坐标系:相对坐标,其X Y Z 指向模型的前后左右上下
坐标轴的含义:
- X:Right 向右
- Y:up 向上
- Z:forward 向前,一般要求模型直面与Z轴方向一致。
组件Component
常见组件:
- Light:光照
- Mesh Filter:网格过滤器,加载网格数据
- Mesh Renderer:网格渲染器,无渲染物体无法显示
组件的增添与删除…
AudioSource组件的使用方式:
1.添加一个音乐文件 *.mp3/wav/aiff
2.创建一个物体
- Add Component,Audio | Audio Source
- 将音乐文件拖到Audiosource.AudioClip属性
- 在3D窗口上方选 Toggle Audio On
Transform变换组件:
- Position:方位
- Rotation:旋转
- Scale:尺寸
摄像机组件
实用操作:
Align with View
:调整摄像机角度使其与3D视图对齐。
预制体简述
预制体:预先规定好信息的一些游戏对象。以便于下次使用。
一些细节:
- 预制体导出时需要勾选其依赖(材质,脚本等),否则无法正常使用。
- 预制体仅仅记录了结点信息
- prefab
不包含材质贴图数据
,仅包含引用
脚本与编程
给游戏对象挂载脚本的步骤:
- 创建Scripts文件夹,在其中创建一个C#文件
- 进入C#,编写代码,并保存
- 将脚本文件挂载到游戏对象中(拖拽 or AddComponent)即可
Tips:
- C#文件名必须和类名一致,否则无法挂载
- 脚本必须被挂载到物体上,才会被调用
常用的信息代码:
GameObject obj = this.gameObject; //获取到当前脚本挂载游戏对象
string name = obj.name; //获取到游戏对象名字
Transform tr = obj.transform; // 获取到Transform属性
Vector3 pos = tr.position; //获取到Transfrom中的position值(返回值是三维向量)
Debug.Lo("物体当前的位置:"+pos.ToString("F3")); //保留三位小数
//世界坐标和本地坐标
//this.gameObject.transform 可等效写为 this.transform
tr.localPosition; //本地坐标
tr.position; //世界坐标
//修改某物体的坐标
this.transform.localPosition = new Vector3(1.5f, 2.5f, 0);
帧更新与物体运动
C#代码中的Update()方法:
void Update()
//Debug.Log("帧更新 Time:" + Time.time); // 获取游戏时间,测试帧率
//Debug.Log("帧更新 时间差:" + Time.deltaTime); // 每次刷新的时间差
//物体移动
//设置小车运动的速度
float speed = 100;
float distance = speed * Time.deltaTime;
Vector3 pos = this.transform.localPosition;
pos.z += distance;
this.transform.localPosition = pos;
//使用Translate方法实现物体移动
this.transform.Translate(0, 0, distance);
//dx,dy,dz分别为三个方向的增量,space可选择相对于哪个坐标系
this.transform.Translate(dx,dy,dz,space);
//例子
this.transfrom.Translate(distance,0,distance,Space.Self/World)
物体转向
void Start()
//转向(在途中加入一个红旗,获取到红旗方向,让小车向红旗方向运行)
GameObject flag = GameObject.Find("红旗");
this.transform.LookAt(flag.transform);
void Update()
float speed = 100;
float distance = speed * Time.deltaTime;
this.transform.Translate(0,0,distance,Space.Self);
小练习:当车到达旗子时,停止运动
public class SimpleLogic : MonoBehaviour
GameObject flag;
// Start is called before the first frame update
void Start()
flag = GameObject.Find("红旗");
this.transform.LookAt(flag.transform);
// Update is called once per frame
void Update()
//让小车到达红旗时停下来
Vector3 p1 = this.transform.position;
Vector3 p2 = flag.transform.position;
Vector3 p = p2 - p1;
//求得两个向量的模值
float length1to2 = p.magnitude;
if (length1to2 >= 30)
//设置小车运动的速度
float speed = 100;
float distance = speed * Time.deltaTime;
this.transform.Translate(0, 0, distance, Space.Self);
物体的旋转
方式一:采用传统的改Rotation值的方式
//不易操作,官方不建议使用
transform.rotation=...
//建议使用欧拉角的方式
方式二:采用欧拉角的计算方法
transform.eulerAngles = new Vector3(0,45,0)
transform.localEulerAngles = new Vector3(0,45,0);
案例:将游戏对象 风扇 转起来
方案一:使用传统欧拉角
void Update()
//旋转速度(1800°/s)
float rotateSpeed = 1800;
float rotateValue = rotateSpeed * Time.deltaTime;
Vector3 angles = this.transform.localEulerAngles;
angles.y += rotateValue;
this.transform.localEulerAngles = angles;
方案二:使用Rotate() API直接调用
void Update()
//设置旋转速度
float rotateSpeed = 1800;
this.transform.Rotate(0,rotateSpeed * Time.deltaTime,0,Space.Self);
脚本与编程的实质:
//unity框架会自动创建游戏对象为一个结点
GameObject obj = new GameObject();
//紧接着创建该游戏结点下挂载的脚本,并由框架挂载到该游戏结点下
SimpleLogic sl = new SimpleLogic();
//并由Unity自动调用Start和Update方法实现初始化和帧更新
消息函数
在c#语言中,所有的脚本类都 应该继承于 MonoBehavior
类,其作用类比于Java中的 Object
类。
消息函数(事件函数):是指一些回调函数。比如Start()方法会在脚本初始化的时候被调用,而Update()会在帧更新的时候被调用。
常见的消息函数:
- Awake:初始化,仅执行一次,组件被禁用时也会调用
- Start:初始化,仅执行一次,组件被禁用时不会调用
- Update:帧更新,每帧调用一次
- OnEnable:当组件启用的时候调用
- OnDisable:当组件禁用时被调用
脚本的执行顺序
- 脚本的执行顺序与Hierarchy中层级顺序无关
- 一般的,可以在Project Setting中的Scripts Execution Order中设置脚本执行的优先级。但没必要!!!
脚本参数:
给脚本添加一个参数:
[ Tooltip("这个是Y轴向的角速度") ]
public float rotateSpeed = 30f;
//在Unity中,脚本参数多了一栏Rotate Speed,值为30
注意事项:
- 修饰符必须为
public
- 参数名称必须采用驼峰式命名
- 可采用Tooltip给参数名称添加解释
- 代码中的规定数值为参数的默认值,通过reset按钮可重置
值类型和引用类型:
值类型:
- 值类型本身是一个值,可直接赋值,若未赋值,则默认为0
- 不能为null
结构体类型:
- 本质也是值类型,不能设置为null
- 设置初始值时必须采用new的方式
- 典例:Vector3
public int intValue ; //0
public float floatValue = 0.5f;
public bool boolValue = true;
public string stringValue = "Hello C-Sharp";
public Vector3 rotateSpeed = new Vector3(1,1,1);
引用类型:
案例:如果一个平面内有两个红旗,我们需要手动规定小车向哪个红旗移动,就可以采用引用类型的属性
public GameObject target; //目标物体
void Start ()
this.transform.LookAt(target.transform);
注意:一定要给引用类型赋值,否则会报 空指针异常
。
鼠标的输入
旋转飞车实例:
void Update()
/*
0:鼠标左键
1:鼠标右键
2:鼠标中键
*/
if (Input.GetMouseButtonDown(0))
Debug.Log("鼠标按下");
rotateSpeed = 900f;
moveSpeed = 300f;
if (Input.GetMouseButtonUp(0))
Debug.Log("鼠标抬起");
rotateSpeed = 0f;
moveSpeed = 0f;
this.transform.Rotate(0, rotateSpeed * Time.deltaTime, 0, Space.Self);
this.transform.Translate(0, 0, moveSpeed * Time.deltaTime, Space.World);
相关API:
GetMouseButtonDown
:鼠标按下GetMouseButtonUp
:鼠标抬起GetMouseButton
:状态探测,只要鼠标按下,会一直调用。
旋转飞车实例2:
void Update()
/*
0:鼠标左键
1:鼠标右键
2:鼠标中键
*/
if (Input.GetMouseButton(0))
rotateSpeed = 900f;
moveSpeed = 300f;
else
rotateSpeed = 0;
moveSpeed = 0;
this.transform.Rotate(0, rotateSpeed * Time.deltaTime, 0, Space.Self);
this.transform.Translate(0, 0, moveSpeed * Time.deltaTime, Space.World);
&一些补充的工具函数
//获取到鼠标点击的位置坐标
Vector3 mousePos = Input.mousePosition;
//获取到屏幕的尺寸
int screenWidth = Screen.width;
int screenHeight = Screen.height;
//获取物体的屏幕坐标
Vector3 pos = this.transform.position;
Vector3 screenPos = Camera.main.WorldToScreenPoint(pos);
键盘的输入
常用API:
Input.GetKeyDown(key)
:按键事件,按下Input.GetKeyUp(key)
:按键事件,抬起Input.GetKey(key)
:案件状态,是否正被按下
代码来操作组件
操作AudioSource组件
//获取到AudioSource组件(泛型)
AudioSource audio = this.GetComponent<AudioSource>();
//播放
audio.Play();
引用别的组件:
应用场景:在主控结点中操作背景音乐的组件
public class MainLogic : MonoBehaviour
//public GameObject bgmNode;
//引用扬声器组件
public AudioSource bgm;
//引用脚本组件
public FanLogic fan;
//风扇转速
public float rotateSpeed;
void Start()
//AudioSource audio = bgmNode.GetComponent<AudioSource>();
//audio.Play();
bgm.Play();
void Update()
if(Input.GetMouseButtonDown(0))
rotateSpeed = 800;
//旋转代码在FanLogic脚本下
获取物体API
案例:主控结点下找到无人机目录下的旋翼对象,并调用它的脚本组件
//主控结点
//方式二:(在Unity中拖入)
public GameObject wingNode;
//方式一:
void Start()
GameObject node = GameObject.Find(无人机/旋翼);
RotateLogic rotateLogic = node.GetComponent<RotateLogic>();
获取游戏节点的父级与子级:
//获取当前组件的父结点与父方位
Transform parent = this.transform.parent;
GameObject parentNode = this.transform.parent.gameObject;
//获取子结点的方位
//方式一:通过foreach遍历
foreach (Transform child in transform)
Debug.Log("子物体" + child.name); //child
//方式二:通过GetChild()索引API
Transform child = this.transform.GetChild(0);
//方式三:通过名字查找子项
Transform child = this.transform.Find("子项名或路径");
给物体设置新的父级:
this.transform.SetParent(null/GameObject);
切换物体的显示状态:
Transform child = this.transform.Find("xxx");
if(child.gameObject.activeSelf)
//隐藏
child.gameObject.SetActive(false);
else
//显示
child.gameObject.SetActive(true);
资源的使用API
用户按下A,D键播放音效成功与失败
//成功音效
public AudioClip audioSuccess;
//失败音效
public AudioClip audioFail;
void Update()
if (Input.GetKeyDown(KeyCode.A))
AudioSource audio = GetComponent<AudioSource>();
audio.PlayOneShot(audioSuccess);
if (Input.GetKeyDown(KeyCode.D))
AudioSource audio = GetComponent<AudioSource>();
audio.PlayOneShot(audioFail);
制作随机音乐盒程序
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MusicBox : MonoBehaviour
public AudioClip[] songs;
// Start is called before the first frame update
void Start()
if (songs == null || songs.Length == 0)
Debug.Log("当前歌单列表为空!");
// Update is called once per frame
void Update()
if (Input.GetKeyDown(KeyCode.Space))
NextSong();
private void NextSong()
//随机播放
int randomIndex = Random.Range(0, songs.Length);
//取到AudioSource组件
AudioSource audio = GetComponent<AudioSource>();
audio.clip = this.songs[randomIndex];
audio.Play();
Debug.Log("正在播放第" + (randomIndex+1) + "首歌,歌名为:" + audio.clip.name);
定时调用与线程
Unity是单线程核心,暂时不必考虑线程,调度,并发。
//延迟调用API
this.Invoke("函数名",延迟时间);
//循环调用API
this.InvokeRepeating("函数名",循环时间间隔);
//查看当前线程的ID
int ThreadId = Thread.CurrentThread.ManagedThreadId;
//判断函数是否正在被调用
bool isInvoking = IsInvoking("函数名");
//取消该函数的调用
CancelInvoke("函数名");
//取消当前脚本所有Invoke调用
CancelInvoke();
向量的基本运算
//定义一个三维向量
Vector3 v1 = new Vector3(3,0,4);
//求向量的模长
float length = v1.magnitude;
//向量标准化
Vector3 v2 = v1.normalized;
//物体运动的优化写法
//定义一个三维向量来表示不同方向的速度
public Vector3 speed;
//优化物体移动写法
void Update()
this.transform.Translate(speed * Time.deltaTime,Space.Self);
预制体与实例
通过API创建实例:
- 首先准备子弹的预制体prefab
- 添加火控脚本 FireLogic.cs
//子弹预制体
public GameObject bulletPrefab;
//子弹目录
public Transform bulletFolder;
//子弹出生点
public Transform firePoint;
//炮塔的引用(为了获取到炮塔发射子弹的方向)
public Transform cannon;
void Update()
//创建实例
GameObject node = Object.Instantiate(bulletPrefab,bulletFolder);
//指定出生点
node.transform.position = this.firePoint.position;
//指定初始角度
node.transform.localEulerAngles = this.cannon.eulerAngles;
//子弹脚本参数的设置(子弹飞行速度)
node.GetComponent<BulletLogic>().setSpeed(0.5f);
- 销毁子弹
//销毁自身结点的API
Object.Destroy(this.gameObject);
//注意不要写错,写为⬇,该写法是销毁组件,而并非结点
Object.Destroy(this);
物理系统与组件
刚体组件
Physic—>RigidBody:刚体组件
常用属性:
- Mass:质量
- Drag:摩擦力
- AngularDrag:角摩擦力
…
Physic—>Collider:碰撞模型
常用类型:BoxCollider,SphereCollider
物理材质Phsicas Material:
- 在Assets中添加一个Physics Material
- 在里面设置全局性的摩擦力Friction,弹性系数等等
碰撞检测
实现 碰撞检测
的步骤:
- RigidBody–>is Kinematic 勾选标记为 运动学刚体
- Collider–>is Tragger 勾选 标记为触发器
- 挂一个脚本,添加消息函数⬇
void OnTriggerEnter(Collider other)
//拿到被碰撞物体的名字
string name = other.name;
//销毁被碰撞物体
Object.Destroy(other.gameObject);
Object.Destroy(this.gameObject);
3D 射击游戏实战
- 1.导入模型
- 2.更改天空盒
Window--->Rendering--->lighting--->environment--->Skybox Material
- 3.添加子弹,模型,材质,脚本等
- 4.给子弹和怪兽添加碰撞检测
- 5.子弹的自动发射,自毁与预制体
- 6.玩家的按键操作
- 7.怪兽的走位移动
- 8.怪兽生成器
- 9.子弹和爆炸特效
源码展示:
子弹BulletLogic:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/*
子弹相关逻辑:
准备工作:子弹的预制体以及导入工程
1.子弹的Z轴移动
2.子弹的自毁
3.子弹的特效导入
*/
public class BulletLogic : MonoBehaviour
//设置子弹的运动速度
[Tooltip("子弹飞行速度")]
public Vector3 speed;
[Tooltip("子弹飞行时长")]
public float lifetime = 5f;
[Tooltip("子弹爆炸特效预制体")]
public GameObject explosionEffect;
// Start is called before the first frame update
void Start()
Invoke("SelfDestroy", lifetime);
// Update is called once per frame
void Update()
this.transform.Translate(speed, Space.Self);
//触发器函数
private void OnTriggerEnter(Collider other)
Debug.Log("发生碰撞了");
//如果碰撞到怪兽
if (!other.name.StartsWith("怪兽")) return;
Destroy(this.gameObject);
Destroy(other.gameObject);
//创建一个爆炸粒子特效对象
GameObject node = Object.Instantiate(explosionEffect,null);
node.transform.position = this.transform.position;
//当粒子特效播放完成时自动销毁
//子弹自毁函数
private void SelfDestroy()
Debug.Log("子弹已自毁");
Destroy(this.gameObject);
玩家PlayerLogic:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/*
玩家相关逻辑:
准备工作:导入玩家模型的预制体资源
1.设置子弹发射点,并实现从该点定时发射子弹
2.添加玩家的按键控制移动
*/
public class PlayerLogic : MonoBehaviour
//预制体资源
public GameObject bulletPrefab;
//子弹生成目录
public Transform bulletFolder;
//子弹发射点
public Transform firePoint;
//子弹发射间隔
public float fireInterval;
//玩家移动速度
public float playerSpeed;
// Start is called before the first frame update
void Start()
InvokeRepeating("fire", fireInterval, fireInterval);
// Update is called once per frame
void Update()
float speedX = 0;
//按键控制
if (Input.GetKey(KeyCode.A))
speedX = -playerSpeed;
else if (Input.GetKey(KeyCode.D))
speedX = playerSpeed;
else
speedX = 0;
this.transform.Translate(speedX * Time.deltaTime, 0, 0, Space.Self);
//发射子弹的函数
private void fire()
//生成一个子弹实例
GameObject bullet = Object.Instantiate(bulletPrefab, bulletFolder);
//设置子弹的出生点
bullet.transform.position = this.firePoint.position;
怪兽EnemyLogic:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/*
怪兽相关逻辑:
准备工作:导入怪兽的预制体进工程
1.水平速度的蛇皮走位逻辑
2.前后速度的固定逻辑
*/
public class EnemyLogic : MonoBehaviour
//水平速度
float speedX = 0;
//前后速度
public float speedZ;
// Start is called before the first frame update
void Start()
//重复周期调用蛇皮走位
InvokeRepeating("move", 0.1f, 0.5f);
// Update is called once per frame
void Update()
this.transform.Translate(speedX * Time.deltaTime, 0, speedZ * Time.deltaTime, Space.Self);
//怪兽的蛇皮走位
private void move()
//设置一个随机速度数组
float[] speed = -5, -10, -20,-30, 5, 10, 20 ,30;
//随机选取一个速度作为水平速度
int rnum = Random.Range(0, speed.Length);
//设置速度
speedX = speed[rnum];
怪兽生成器EnemyCreator:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/*
怪兽生成器相关逻辑:
1.定时生成怪兽即可
*/
public class EnemyCreator : MonoBehaviour
//要创建的怪兽预制体
public GameObject enemyPrefab;
//创建怪物间隔时长
public float enemyInterval = 0.5f;
// Start is called before the first frame update
void Start()
InvokeRepeating("creatEnemy", 0.1f, enemyInterval);
// Update is called once per frame
void Update()
private void creatEnemy()
GameObject node = GameObject.Instantiate(enemyPrefab, this.transform);
node.transform.position = this.transform.position;
//调整随机出生点
int rnum = Random.Range(-50, 50);
node.transform.Translate(rnum, 0, 0, Space.Self);
恭喜未来的游戏开发工程师,正式入门!!!后会有期!!!
Pandas高级数据分析快速入门之二——基础篇
Pandas高级数据分析快速入门之一——Python开发环境篇
Pandas高级数据分析快速入门之二——基础篇
Pandas高级数据分析快速入门之三——统计分析篇
Pandas高级数据分析快速入门之四——表内、表间数据处理篇
Pandas高级数据分析快速入门之五——机器学习特征工程篇
Pandas高级数据分析快速入门之六——机器学习预测分析篇
0. Pandas构成
Pandas由两种常用的数据类型:
(1)Series是一种一维的带标签数组对象;
(2)DataFrame,二维数据表,Series容器。
其中,最常用的是DataFrame,做为数据分析数据载体——二维数据表,基于此有大量的统计分析函数。
DataFrame是一个二维表格型的数据结构,它含有一组有序的列,每列可以是不同的值类型(数值、字符串、布尔值等)。DataFrame既有行索引也有列索引,它可以被看做由Series组成的字典(共用同一个索引)。跟其他类似的数据结构相比(如R的data.frame),DataFrame中面向行和面向列的操作基本上是平衡的。其实,DataFrame中的数据是以一个或多个二维块存放的(而不是列表、字典或别的一维数据结构)。
0.1. 第一个DataFrame
df = pd.DataFrame({'float': [1.0],
'int': [1],
'datetime': [pd.Timestamp('20180310')],
'string': ['foo'],
'stringtoint':['666']})
df.dtypes #显示数据类型
float float64
int int64
datetime datetime64[ns]
string object
stringtoint object
dtype: object
0.2. Pandas数据类型
Pandas dtype | Python类型 | Numpy类型 | 说明 |
---|---|---|---|
object | str | string_,unicode_ | 用于文本 |
int64 | int | int_,int8_,int16,int32,int64,uint8,uint16,uint32,uint64 | 用于整数 |
float64 | float | float_,float16,float32,float64 | 用于浮点数 |
bool | bool | bool_ | 用于布尔值 |
datetime64 | NA | NA | 用于日期时间 |
timedelta[ns] | NA | NA | 用于时间差 |
category | NA | NA | 用于有限长度的文本值列表 |
0.3. Pandas数据类型转换
df['stringtoint'] = df['stringtoint'].astype('int64') #object转换为整型
print(df)
print(df.dtypes)
float int datetime string stringtoint
0 1.0 1 2018-03-10 foo 666
float float64
int int64
datetime datetime64[ns]
string object
stringtoint int64
dtype: object
0.4. 用到的Python基础
0.4.1. 序列(List)
序列是 Python 中最基本的数据结构。
序列中的每个值都有对应的位置值,称之为索引,第一个索引是 0,第二个索引是 1,依此类推。
list = ['Google', 'Runoob', 1997, 2000]
print ("第三个元素为 : ", list[2])
list[2] = 2001
print ("更新后的第三个元素为 : ", list[2])
list1 = ['Google', 'Runoob', 'Taobao']
list1.append('Baidu')
print ("更新后的列表 : ", list1)
第三个元素为 : 1997
更新后的第三个元素为 : 2001
更新后的列表 : ['Google', 'Runoob', 'Taobao', 'Baidu']
del list[2]
print ("删除第三个元素 : ", list)
list.remove('Google')
print ("删除Google元素 : ", list)
删除第三个元素 : ['Google', 'Runoob', 2000]
删除Google元素 : ['Runoob', 2000]
0.4.2. 字典
字典是另一种可变容器模型,且可存储任意类型对象。
字典的每个键值 key=>value 对用冒号 : 分割,每个对之间用逗号(,)分割,整个字典包括在花括号 {} 中 ,格式如下所示:
d = {key1 : value1, key2 : value2, key3 : value3 }
dict = {'Name': 'Runoob', 'Age': 7, 'Class': 'First'}
print ("dict['Name']: ", dict['Name'])
print ("dict['Age']: ", dict['Age'])
dict['Age'] = 10
print ("dict['Age']: ", dict['Age'])
dict['Name']: Runoob
dict['Age']: 7
dict['Age']: 10
1. 从读取通用数据文件开始
Pandas直接读取CSV、Excel、Json等数据文件为数据表(DataFrame)。
1.1. 读XLS数据文件
首先,用表格工具新建Excel表“sport.xlsx”,内容以部分田径运动员信息为例如下图所示。
import pandas as pd
df = pd.read_excel('sport.xlsx')
print(df)
id name age Gender sport
0 1001.0 董国建 34.000000 男 马拉松
1 1002.0 苏炳添 31.000000 男 百米
2 1003.0 彭建华 24.000000 男 马拉松
3 1004.0 张德顺 25.000000 女 马拉松
4 1005.0 焦安静 25.000000 女 马拉松
5 1006.0 葛曼棋 24.000000 女 百米
6 NaN 6 27.166667 NaN NaN
1.2. 读CSV数据文件
用文本编辑器工具新建CSVl表“sport.csv”,内容如下图所示。
import pandas as pd
df = pd.read_csv('sport.csv',encoding='utf_8')
print(df)
Name Team Grander Birth Age
0 董国建 马拉松 男 1987-3-16 34.0
1 苏炳添 百米 男 1981-8-29 31.0
2 张德顺 马拉松 女 1996-2-21 25.0
3 葛曼棋 百米 女 1997-10-13 24.0
2. 对表(DataFrame)增减数据
2.1. 增减行数据
2.1.1. 增加行
按索引行赋值,数据格式为列表(List)。
df.loc[4] = ['焦安静','马拉松','女','1995-9-3',26.0] #按索引增加行
#如下增加数据行都是有效的,并且不依赖索引
df.append(pd.DataFrame({'Name':['彭建华'],'Team':['马拉松'],'Grander':['男'],'Birth':['1996-12-18'],'Age':[25.0]}), ignore_index=True)
df=df.append({'Name':'杨绍辉','Team':'马拉松','Grander':'男','Birth':'1992-7-9','Age':29.0}, ignore_index=True)
print(df)
Name Team Grander Birth Age
0 董国建 马拉松 男 1987-3-16 34.0
1 苏炳添 百米 男 1981-8-29 31.0
2 张德顺 马拉松 女 1996-2-21 25.0
3 葛曼棋 百米 女 1997-10-13 24.0
4 焦安静 马拉松 女 1995-9-3 26.0
5 杨绍辉 马拉松 男 1992-7-9 29.0
2.1.2. 删除行
按索引行删除数据行。
df = df.drop(index=[5]).reset_index(drop=True)
print(df)
Name Team Grander Birth Age
0 董国建 马拉松 男 1987-3-16 34.0
1 苏炳添 百米 男 1981-8-29 31.0
2 张德顺 马拉松 女 1996-2-21 25.0
3 葛曼棋 百米 女 1997-10-13 24.0
4 焦安静 马拉松 女 1995-9-3 26.0
按条件筛选数据行(获取索引)而删除数据行。
df=df.drop(df.loc[df['Name']=='焦安静'].index)
print(df)
Name Team Grander Birth Age
0 董国建 马拉松 男 1987-3-16 34.0
1 苏炳添 百米 男 1981-8-29 31.0
2 张德顺 马拉松 女 1996-2-21 25.0
3 葛曼棋 百米 女 1997-10-13 24.0
2.2. 增减列数据
2.2.1. 增加列数据
通过序列数据(List),直接增加列,其中,要求序列数组个数与数据行数保持一致。
native = ['重庆','广东','云南','福建']
df['Native']=native
# 以下方法都可以插入列数据
#df.loc[:,'Native'] = native
#df.insert(1,'Native',native) # 在指点位置(列),插入列数据
print(df)
Name Team Grander Birth Age Native
0 董国建 马拉松 男 1987-3-16 34.0 重庆
1 苏炳添 百米 男 1981-8-29 31.0 广东
2 张德顺 马拉松 女 1996-2-21 25.0 云南
3 葛曼棋 百米 女 1997-10-13 24.0 福建
2.2.2. 删除列数据
按列名删除数据。
df=df.drop(['Birth'],axis=1)
print(df)
Name Team Grander Age Native
0 董国建 马拉松 男 34.0 重庆
1 苏炳添 百米 男 31.0 广东
2 张德顺 马拉松 女 25.0 云南
3 葛曼棋 百米 女 24.0 福建
通过筛选数据子表方法,达到删除数据的效果,原数据仍得以保留。先从DataFrame中获取列名为List数据类型,再删除其中不需要的列(可以多个),然后,再通过筛选数据方式获得新的数据表。
#df.columns 返回Index,可以通过 tolist(), 或者 list(array) 转换为list
cols = df.columns.tolist()
cols.remove('Native')
df = df[cols]
print(df)
Name Team Grander Age
0 董国建 马拉松 男 34.0
1 苏炳添 百米 男 31.0
2 张德顺 马拉松 女 25.0
3 葛曼棋 百米 女 24.0
3. 把数据保存到CSV文件
# encoding设置是针对中文问题,如果系统以及设置为中文,则可以略去
df.to_csv('sport_update.csv',encoding='utf_8_sig')
# 保存文件不带索引,我比较喜欢
df.to_csv('sport_noindex.csv',encoding='utf_8_sig',index=False)
# 保存文件不带表头(header)
df.to_csv('sport_noheader.csv',encoding='utf_8_sig',header=False)
# 对于不带表头的数据读取,需要设置header=None,否则,第一行数据变成表头
df1 = pd.read_csv('sport_noheader.csv',encoding='utf_8',header=None)
print(df1)
0 1 2 3 4
0 0 董国建 马拉松 男 34.0
1 1 苏炳添 百米 男 31.0
2 2 张德顺 马拉松 女 25.0
3 3 葛曼棋 百米 女 24.0
4. DataFrame单元格操作
4.1. 读取单元格数据
print('iloc[[1],[1]]: ' + df.iloc[[1],[1]])
print('iloc[1,1]: ' + df.iloc[1,1])
print(df.loc[1],[1])
Team
1 iloc[[1],[1]]: 百米
iloc[1,1]: 百米
Name 苏炳添
Team 百米
Grander 男
Birth 1981-8-29
Age 31
Name: 1, dtype: object [1]
4.2. 修改单元格数据
按索引及列位置顺序修改单元格数据。
# 后增加内容,后面讲
df.iloc[1,1] = '田径'
print(df)
Name Team Grander Birth Age
0 董国建 马拉松 男 1987-3-16 34.0
1 苏炳添 田径 男 1981-8-29 31.0
2 张德顺 马拉松 女 1996-2-21 25.0
3 葛曼棋 百米 女 1997-10-13 24.0
4 焦安静 马拉松 女 1995-9-3 26.0
5 杨绍辉 马拉松 男 1992-7-9 29.0
按筛选条件:“Name”等于“苏炳添”,定位列名为“Team”修改单元格数据。
df.loc[df.loc[df['Name']=='苏炳添'].index,'Team'] = '马拉松'
print(df)
Name Team Grander Birth Age
0 董国建 马拉松 男 1987-3-16 34.0
1 苏炳添 马拉松 男 1981-8-29 31.0
2 张德顺 马拉松 女 1996-2-21 25.0
3 葛曼棋 百米 女 1997-10-13 24.0
4 焦安静 马拉松 女 1995-9-3 26.0
5 杨绍辉 马拉松 男 1992-7-9 29.0
按索引及列名为“Team”修改单元格数据。
df.loc[1,'Team'] = '百米'
print(df)
Name Team Grander Birth Age
0 董国建 马拉松 男 1987-3-16 34.0
1 苏炳添 百米 男 1981-8-29 31.0
2 张德顺 马拉松 女 1996-2-21 25.0
3 葛曼棋 百米 女 1997-10-13 24.0
4 焦安静 马拉松 女 1995-9-3 26.0
5 杨绍辉 马拉松 男 1992-7-9 29.0
5. 读取Clickhouse数据
使用clickhouse_driver 接口,查询数据返回DataFrame格式数据。
from clickhouse_driver import Client
db_name = 'ebd_all_b04'
host='192.168.17.61' #服务器地址
port ='9000'
database=db_name #数据库
send_receive_timeout = 25 #超时时间
client = Client(host=host, port=port, database=database)
query_sql = '''select E.carduser_id,anyLast(E.p500) as p500,anyLast(E.org_id) as org_id,E.occurday as occurday,
anyLast(E.balance) as balance,sum(recharge) as recharge,sum(volumn) as volumn,
sum(all_oils) as all_oils,sum(all_goods) as all_goods,sum(E.discount) as discount,
max(goodscategory_id) as goods_id,count(*) as trans_sum from (
......
group by E.carduser_id,E.occurday
order by E.carduser_id,E.occurday
'''
# 查询直接返回DataFrame
collection = client.query_dataframe(query_sql)
print(collection)
carduser_id p500 org_id occurday balance recharge volumn \\
0 131***3 101*** 102*** 2017-04-29 600 20000 3205
1 131***3 101*** 102*** 2017-05-12 1575 10000 0
2 131***3 101*** 102*** 2017-05-14 2575 20000 0
3 131***3 101*** 102*** 2017-05-18 6305 10000 0
all_oils all_goods discount goods_id trans_sum
0 -19400 0 -600 101701.0 2
1 0 -9025 -475 100016.0 2
2 0 -19000 -1000 100016.0 3
3 0 -6270 -330 100073.0 2
[3193 rows x 12 columns]
参考:
肖永威 ,Python使用ClickHouse实践与踩坑记 , CSDN博客 ,2021.06
以上是关于Unity3D入门篇的主要内容,如果未能解决你的问题,请参考以下文章
unity3d游戏开发和unity入门到精通哪本书适合初学者