Unity基础(18)-影音系统

2020-06-02 15:06:31 浏览数 (1)

01-声音播放

声音播放组件

代码语言:javascript复制
    // 声音组件(可手动添加,也可如下代码添加) 
    private AudioSource audio;
    // 声音片段(音频格式都支持)
    public AudioClip clip;
    void Start () {
         
        audio = this.gameObject.AddComponent<AudioSource>();
        // 一开始就播放
        audio.playOnAwake = true;
        // 声音片段
        audio.clip = clip;
        // 设置循环播放
        audio.loop = true;
        // 音量大小
        audio.volume = 0.2f;
        // 倍率播放(2倍播放)
        audio.pitch = 2f;
        // 静音播放
        audio.mute = true;
    }
    
    void Update () {
        if (Input.GetMouseButtonDown(0))
        {
            // 播放声音
            audio.Play();
        }
        if (Input.GetMouseButtonDown(1))
        {
            // 暂停播放
            audio.Pause();
        }
        if (Input.GetMouseButtonDown(2))
        {
            // 停止播放
            audio.Stop();
        }
    }
02-视频播放
  • PC端MovieTexture 优点:简单,高效的快速完成播放 缺点:此种方法无法应用于移动端。movietexture只能播放OGG和OVG
代码语言:javascript复制
    // 视频片段 
    public MovieTexture video;
    // 声音片段
    public AudioClip clip;
    // 声音播放组件
    private AudioSource audio;
    
    void Start () {
        // 拿到Renderer的材质,设置里面的主贴图 = 视频片段
        this.gameObject.GetComponent<Renderer>().material.mainTexture = video;
        audio = this.gameObject.AddComponent<AudioSource>();
        audio.clip = clip; 
        // 循环播放
        video.loop = true;
        audio.loop = true;
        // 判断当前视频是否在播放
        if (video.isPlaying)
        {
            Debug.Log("判断视频是否播放");
        }
        // 视频的名字
        string name = video.name;
        Debug.Log(name);
    }   
    private void OnGUI()
    {
        if (GUILayout.Button("播放"))
        {
            audio.Play();
            video.Play();
        }
        if (GUILayout.Button("暂停"))
        {
            audio.Pause();
            video.Pause();
        }
        if (GUILayout.Button("停止"))
        {
            audio.Stop();
            video.Stop();
        }
    }
}
  • 移动端Handheld
    • 缺点: 可操作性非常差,几乎达不到我们想要的结果,而且也只支持全屏的普通视频的播放。
代码语言:javascript复制
设置播放(视频路径,背景色,如何显示播放控件,如何缩放电影以适应屏幕)
PlayFullScreenMovie(string path, [DefaultValue("Color.black")] Color bgColor,[DefaultValue("FullScreenMovieControlMode.Full")] FullScreenMovieControlMode controlMode, [DefaultValue("FullScreenMovieScalingMode.AspectFit")] FullScreenMovieScalingMode scalingMode);
PlayFullScreenMovie(string path, Color bgColor, FullScreenMovieControlMode controlMode);
PlayFullScreenMovie(string path, Color bgColor);
PlayFullScreenMovie(string path);
// 设置样式方法(IOS,Android,列举)
SetActivityIndicatorStyle(ActivityIndicatorStyle style)
SetActivityIndicatorStyle(AndroidActivityIndicatorStyle style)
SetActivityIndicatorStyle(TizenActivityIndicatorStyle style)
// 获取当前的活动指示器样式。他获取的就是安卓苹果即列举的所有样式
GetActivityIndi​​catorStyle();
// 停止控制器(活动指示器)
StopActivityIndi​​cator();
// 触发设备振动
Vibrate();
// 启动操作系统活动指示器。为了让实际的动画生效,你通常需要等到这个帧结束。所以如果你希望活动指示器在同步操作中动画,请使用协程
StartActivityIndi​​cator

启动操作系统活动指示器:

代码语言:javascript复制
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;

public class Example2 : [MonoBehaviour](https://docs.unity3d.com/ScriptReference/MonoBehaviour.html)
{
    IEnumerator Load()
    {
        #if UNITY_IPHONE
        Handheld.SetActivityIndicatorStyle(iOS.ActivityIndicatorStyle.Gray);
        #elif UNITY_ANDROID
        Handheld.SetActivityIndicatorStyle(AndroidActivityIndicatorStyle.Small);
        #elif UNITY_TIZEN
        Handheld.SetActivityIndicatorStyle(TizenActivityIndicatorStyle.Small);
        #endif
        Handheld.StartActivityIndicator();
        yield return new WaitForSeconds(0);
        SceneManager.LoadScene("My Next Scene");
    }

    void OnGUI()
    {
        if (GUI.Button(new Rect(10, 10, 200, 200), "Load!"))
            StartCoroutine(Load());
    }
}
  • FullScreenMovieControlMode 如何显示播放控件枚举

FullScreenMovieControlMode

  • FullScreenMovieScalingMode 缩放电影以适应屏幕枚举

FullScreenMovieScalingMode

  • AndroidActivityIndicatorStyle : 安卓设备上的样式 如下:

安卓平台

  • ActivityIndicatorStyle iOS设备上样式 如下:

iOS平台样式

  • TizenActivityIndi​​catorStyle

列举样式

注意点: 将视频文件放置在Assets/StreamingAssets/路径下,经测试.MP4可用。最好通过网络加载的方式进行下载,避免打包程序过大。用完设置一个保存时间,一个月或者7天删除。

StreamingAssets

代码语言:javascript复制
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Handle : MonoBehaviour {
        string path;
    void Start () {
        path = "02.mp4";

        Handheld.StartActivityIndicator();
        Handheld.Vibrate();
    }
    private void OnGUI()
    {
        if(GUILayout.Button("全屏播放"))
         {
            Handheld.PlayFullScreenMovie(path,Color.black,FullScreenMovieControlMode.Full);
        }
        if (GUILayout.Button("显示控件最少的播放"))
        {
            Handheld.PlayFullScreenMovie(path, Color.black, FullScreenMovieControlMode.Minimal);
        }
        if (GUILayout.Button("不显示控件的播放"))
        {
            Handheld.PlayFullScreenMovie(path, Color.black, FullScreenMovieControlMode.Hidden);
        }
        if (GUILayout.Button("不显示控件输入取消播放"))
        {
            Handheld.PlayFullScreenMovie(path, Color.black, FullScreenMovieControlMode.CancelOnInput);
        }
    }
  • 全能VideoPlayer (Unity5.6之后) Unity5.6后,结合之前Unity特别难受的播放器,推出了新的VideoPlayer。支持大部分格式,无需转码。

VideoPlayer组件

  • 属性

属性

属性

属性

代码语言:javascript复制
using UnityEngine;
using UnityEngine.Video;

public class VideoScripts : MonoBehaviour {

    private VideoPlayer videoPlayer;
    public VideoClip clip;
    private AudioSource audioSource;
    // Use this for initialization
    void Start () {
        videoPlayer = this.gameObject.AddComponent<VideoPlayer>();
        audioSource = this.gameObject.AddComponent<AudioSource>();

        videoPlayer.playOnAwake = false;
        audioSource.playOnAwake = false;

        // 设置输出模式
        videoPlayer.audioOutputMode = VideoAudioOutputMode.AudioSource;

        // 如果使用VideoPlayer.audioOutputMode选择此音频目标,则设置将接收指定音轨音频样本的AudioSource
        videoPlayer.SetTargetAudioSource(0, audioSource);

        // 一开始没有声音就可以使用此方法
        videoPlayer.EnableAudioTrack(0, true);

        Debug.Log(videoPlayer.IsAudioTrackEnabled(0));
    }
    private void OnGUI()
    {
        if (GUILayout.Button("播放"))
        {
            videoPlayer.clip = clip;
            videoPlayer.Play();
            Debug.Log(videoPlayer.IsAudioTrackEnabled(0));
        }
        if (GUILayout.Button("暂停"))
        {
            videoPlayer.Pause();
        }
        if (GUILayout.Button("停止"))
        {
            videoPlayer.Stop();
        }
        if (GUILayout.Button("3倍速度播放"))
        {
            videoPlayer.playbackSpeed = 3f;
        }
    }
}

方法

事件

代理

  • iOS原生视频播放
代码语言:javascript复制
using UnityEngine;  
using System.Collections;  
using System.Runtime.InteropServices;  
public class NewBehaviourScript : MonoBehaviour {  
  
[DllImport("__Internal")] //声明是调用ios代码  
private static extern void setIosVideoUrl(string url,string objName);  
[DllImport("__Internal")]  
private static extern void setIosVideoRect(int left,int top,int width,int height);  
[DllImport("__Internal")]  
 private static extern void VideoPlay();  
  
    void Start () {   
         //视频要放在AssetsStreamingAssets 路径下面  
         setIosVideoUrl("test.mp4","当前挂载脚本物体名称"); //这里就可以直接调用  
         setIosVideoRect(20,20,200,200);  
         VideoPlay();   
    }        
}  

ios里面调用视频播放的接口代码

代码语言:javascript复制
#include <string>  
#import "AVPlayerController.h"  
  
using namespace std;  
  
extern "C"{  
    void setIosVideoUrl(char* url,char* objName); //这个方法正好对应上面c#代码方法 注意c#是string这里是char*  
    void setIosVideoRect(int left,int top,int width,int height);  
    void VideoPlay();  
    void VideoPause();  
    void VideoResume();  
    void VideoStop();  
    void VideoReplay();  
    void VideoRelease();  
}  
void setIosVideoUrl(char* url,char* objName){  <pre name="code" class="csharp">      
// unity路径下视频路径是AssetsStreamingAssets下 打包到ios路径变成DataRaw下了  这里做了一下处理  
//把 101.mp4 改成 Data/Raw/101.mp4  
  
    AVPlayerController * avp = [AVPlayerController shareInstance];  
      
    NSString* str = [NSString stringWithCString:url encoding:NSUTF8StringEncoding];  
    NSLog(@"AA ---  %@",str);  
      
    NSString* str3 = [NSString stringWithCString:objName encoding:NSUTF8StringEncoding];  
    NSLog(@"BB ---  %@",str3);  
      
    NSString *topStr = @"Data/Raw/";  
    NSString *strAdd = [topStr stringByAppendingString:str];  
    NSString *strUrl = [strAdd stringByReplacingOccurrencesOfString:@".mp4" withString:@""];  
    NSLog(@"UUU ---  %@",strUrl);  
      
    [avp setURL:strUrl UnityObj:objName];  
}  
  
  
void setIosVideoRect(int left,int top,int width,int height){  
    AVPlayerController * avp = [AVPlayerController shareInstance];  
    [avp setRect:left/2 TOP:top/2 WIDTH:width/2 HEIGHT:height/2]; //这里我除以2是做了特殊处理 可以不除以2  
      
    NSLog(@"left:%d,top:%d,width:%d,height:%d",left/2,top/2,width/2,height/2);  
}  
  
  
void VideoPlay(){  
    AVPlayerController * avp = [AVPlayerController shareInstance];  
    [avp play];  
}  
  
void VideoPause(){  
    AVPlayerController * avp = [AVPlayerController shareInstance];  
    [avp pause];  
}  
void VideoRelease(){  
    AVPlayerController * avp = [AVPlayerController shareInstance];  
    [avp removePlayer];  
}  

视频播放代码

代码语言:javascript复制
#import <AVFoundation/AVFoundation.h>  
#import <Foundation/Foundation.h> //这是要引入的头文件  
  
@interface AVPlayerController : NSObject  
  
 (id)shareInstance; //静态方法 相当于c#中的单列 (这个类只要初始化一次就可以了)  
  
@property (nonatomic,strong) AVPlayer *avPlayer;//播放器对象  
  
@property (nonatomic,strong) AVPlayerLayer* playerLayer;  
  
@property (nonatomic,strong) AVPlayerItem* playerItem;  
  
@property (nonatomic,readwrite) float playerDuration;  
  
@property (nonatomic,strong) NSString* unityObjectName;  
  
  
- (void)setURL:(NSString*)videoUrl UnityObj:(char*)objName;  
  
- (void)setRect:(int)left TOP:(int)top WIDTH:(int)width HEIGHT:(int)height;  
  
- (void)play;  
  
- (void)pause;  
  
- (void)removePlayer;  
  
- (void)playbackFinished:(NSNotification *)notification;  
  
- (bool)isPlaying;  
@end  
代码语言:javascript复制
#import "AVPlayerController.h"  
  
static AVPlayerController *avp = nil;  
  
@implementation AVPlayerController  
  
 (id)shareInstance{  
    if(avp == nil){  
        avp = [[super allocWithZone:nil]init];  
    }  
    return avp;  
}  
  
 (id)allocWithZone:(NSZone *)zone{  
    return [AVPlayerController shareInstance];  
}  
  
//- (void) dealloc{  
//    //移除播放完成通知  
//    [[NSNotificationCenter defaultCenter] removeObserver:self];  
//}  
  
- (void)setURL:(NSString*)videoUrl UnityObj:(char*)objName{ //这个播放方法想了解 可以百度搜索下  
    NSString *path=[[NSBundle mainBundle] pathForResource:videoUrl ofType:@"mp4"];  
    NSURL* movieURL = [NSURL fileURLWithPath:path];  
    AVAsset* movieAsset = [AVURLAsset URLAssetWithURL:movieURL options:nil];  
    self.playerItem = [AVPlayerItem playerItemWithAsset:movieAsset];  
    self.avPlayer = [AVPlayer playerWithPlayerItem:self.playerItem];  
    self.playerLayer = [AVPlayerLayer playerLayerWithPlayer:self.avPlayer];  
    self.playerLayer.videoGravity = AVLayerVideoGravityResize;  
    [UnityGetGLViewController().view.layer addSublayer:self.playerLayer];//注意 这个方法很重要(把ios视图添加到unity中)  
      
    self.unityObjectName = [NSString stringWithCString:objName encoding:NSUTF8StringEncoding];  
  
    [self addNotification];  
  
    CMTime duration = self.avPlayer.currentItem.asset.duration;  
    float seconds = CMTimeGetSeconds(duration);  
    self.playerDuration = seconds;  
    NSLog(@"总时长%.2fs.",seconds);  
}  
  
- (void)setRect:(int)left TOP:(int)top WIDTH:(int)width HEIGHT:(int)height{ //这个方法设置视频位置和长宽  
    self.playerLayer.frame = CGRectMake(left, top, width, height);  
}  
  
- (void)play{  
    [self.avPlayer play];  
}  
  
- (void)pause{  
    [self.avPlayer pause];  
}  
  
- (bool)isPlaying{  
    if(self.avPlayer.rate == 0){  
        NSLog(@"当前状态:暂停");  
        return false;  
    }  
      
    if(self.avPlayer.rate == 1){  
        NSLog(@"当前状态:播放");  
        return true;  
    }  
    return false;  
}  
  
-(void)addNotification{  
    //给AVPlayerItem添加播放完成通知 (不执行? 擦又可以了)  
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playbackFinished:) name:AVPlayerItemDidPlayToEndTimeNotification object:self.avPlayer.currentItem];  
      
    //这里设置每秒执行一次 用这个方法代替播放完成通知 (上面可以 暂时弃用)  
//    [self.avPlayer addPeriodicTimeObserverForInterval:CMTimeMake(1.0, 1.0) queue:dispatch_get_main_queue() usingBlock:^(CMTime time) {  
//        float current=CMTimeGetSeconds(time);  
////        NSLog(@"%f",current);  
//        if(current >= self.playerDuration)  
//        {  
//            NSLog(@"视频播放完成");  
//        }  
//    }];  
}  
  
-(void)playbackFinished:(NSNotification *)notification{  
    NSLog(@"video play finished!");  
    const char* unityObjName = [self.unityObjectName UTF8String];      
    UnitySendMessage(unityObjName, "OSVideoCallback", "EVENT_COMPLETED");//ios发送消息告诉unity视频播放完成  
}  
  
  
- (void)removePlayer{  
    [self.playerLayer removeFromSuperlayer];  
    self.playerLayer = nil;  
    self.avPlayer = nil;  
    self.playerItem = nil;  
    [[NSNotificationCenter defaultCenter] removeObserver:self];  
    self.playerDuration = 0;  
}  
  
@end  

0 人点赞